diff --git a/.asf-release/.gitkeep b/.asf-release/.gitkeep new file mode 100644 index 00000000..a926db80 --- /dev/null +++ b/.asf-release/.gitkeep @@ -0,0 +1,22 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# --- +# This directory is used as apart of the release process. +# Package tarballs will be generated in stored temporarily +# within this directory and should not be commited to repo. +# --- diff --git a/.asf.yaml b/.asf.yaml new file mode 100644 index 00000000..5bba3265 --- /dev/null +++ b/.asf.yaml @@ -0,0 +1,58 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +github: + description: Apache Cordova - Xcode Node + homepage: https://cordova.apache.org/ + + labels: + - cordova + - mobile + - ios + - javascript + - nodejs + - hacktoberfest + + features: + wiki: false + issues: true + projects: true + + enabled_merge_buttons: + squash: true + merge: false + rebase: false + + rulesets: + - name: "Default Branch Protection" + type: branch + branches: + includes: + - "~DEFAULT_BRANCH" + - "release/*" + - "rel/*" + excludes: [] + bypass_teams: + - root + restrict_deletion: true + restrict_force_push: true + +notifications: + commits: commits@cordova.apache.org + issues: issues@cordova.apache.org + pullrequests_status: issues@cordova.apache.org + pullrequests_comment: issues@cordova.apache.org diff --git a/Makefile b/.gitattributes similarity index 78% rename from Makefile rename to .gitattributes index 8e42288f..32f4c2b3 100644 --- a/Makefile +++ b/.gitattributes @@ -1,4 +1,3 @@ -# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -7,18 +6,13 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the +# KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -# - -tests: - nodeunit test/* test/parser/* -parser: - pegjs lib/parser/pbxproj.pegjs +*.pbxproj eol=lf diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..609ac461 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,52 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + cooldown: + default-days: 5 + schedule: + interval: "weekly" # Every Monday + groups: + gh-actions-patch-minor: + patterns: + - "*" + update-types: + - "patch" + - "minor" + + - package-ecosystem: "npm" + directory: "/" + cooldown: + default-days: 5 + semver-major-days: 14 + schedule: + interval: "weekly" # Every Monday + groups: + npm-patch: + patterns: + - "*" + update-types: + - "patch" + npm-minor: + patterns: + - "*" + update-types: + - "minor" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..cb84c88e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,122 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Node CI + +on: + push: + branches-ignore: + - 'dependabot/**' + pull_request: + branches: + - '*' + +jobs: + codeql: + name: CodeQL Analysis + runs-on: ubuntu-latest + + permissions: + contents: read + security-events: write + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + fetch-depth: 1 + + - uses: github/codeql-action/init@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + with: + languages: javascript + queries: security-and-quality + config: | + paths-ignore: + - coverage + - node_modules + + - uses: github/codeql-action/analyze@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0 + + test: + name: NodeJS ${{ matrix.node.version }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + + permissions: + contents: read + + strategy: + matrix: + os: [windows-latest, ubuntu-latest, macos-26] + # The "--test-coverage-exclude" flag is supported in v22.5.0 and later. + # By default, all matching test files are excluded from the coverage report. + # Only Node.js 22.x requires explicitly declaring test file exclusions. + node: + - version: 20 + - version: 22 + options: --test-coverage-exclude="test/**/*.js" + - version: 24 + - version: 26 + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + fetch-depth: 1 + + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: ${{ matrix.node.version }} + + - name: Environment Information + run: | + node --version + npm --version + + - name: npm install + run: npm ci + env: + CI: true + NODE_OPTIONS: ${{ matrix.node.options }} + + - name: Build parser + run: npm run build + env: + CI: true + NODE_OPTIONS: ${{ matrix.node.options }} + + - name: Check for uncommitted changes + if: ${{ ! startsWith(matrix.os, 'windows') }} + run: | + if ! git diff --exit-code; then + echo "" + echo "::error::Detected changes that appear to not be committed." + echo "::error::Please run 'npm run build' and commit the built parser." + exit 1 + fi + + - name: npm test + run: npm t + env: + CI: true + NODE_OPTIONS: ${{ matrix.node.options }} + + - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 + if: success() + with: + name: ${{ runner.os }} node.js ${{ matrix.node.version }} + token: ${{ secrets.CORDOVA_CODECOV_TOKEN }} + fail_ci_if_error: false diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml new file mode 100644 index 00000000..f744fe1b --- /dev/null +++ b/.github/workflows/draft-release.yml @@ -0,0 +1,155 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Draft Release + +on: + push: + tags: + - 'draft/**' + +permissions: + contents: read + id-token: write + +jobs: + upload-to-atr: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + fetch-depth: 1 + + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 24 + package-manager-cache: false + cache: '' + + - name: Setup environment variables + run: | + REPO_NAME="${GITHUB_REPOSITORY#*/}" + TAG_NAME="${GITHUB_REF#refs/tags/}" + TARGET_RELEASE_VERSION="${TAG_NAME#draft/}" + SRC_PACKAGE_NAME=${REPO_NAME}-source-${TARGET_RELEASE_VERSION} + SRC_PACKAGE_TAR=${SRC_PACKAGE_NAME}.tar + SRC_PACKAGE_TAR_GZ=${SRC_PACKAGE_NAME}.tar.gz + SRC_PACKAGE_ZIP=${SRC_PACKAGE_NAME}.zip + NPM_PACKAGE_NAME=${REPO_NAME}-npm-${TARGET_RELEASE_VERSION} + + echo "REPO_NAME=$REPO_NAME" >> $GITHUB_ENV + echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV + echo "TARGET_RELEASE_VERSION=$TARGET_RELEASE_VERSION" >> $GITHUB_ENV + echo "SRC_PACKAGE_NAME=$SRC_PACKAGE_NAME" >> $GITHUB_ENV + echo "SRC_PACKAGE_TAR=$SRC_PACKAGE_TAR" >> $GITHUB_ENV + echo "SRC_PACKAGE_TAR_GZ=$SRC_PACKAGE_TAR_GZ" >> $GITHUB_ENV + echo "SRC_PACKAGE_ZIP=$SRC_PACKAGE_ZIP" >> $GITHUB_ENV + echo "NPM_PACKAGE_NAME=$NPM_PACKAGE_NAME" >> $GITHUB_ENV + + echo "REPO_NAME=$REPO_NAME" + echo "TAG_NAME=$TAG_NAME" + echo "TARGET_RELEASE_VERSION=$TARGET_RELEASE_VERSION" + echo "SRC_PACKAGE_NAME=$SRC_PACKAGE_NAME" + echo "SRC_PACKAGE_TAR=$SRC_PACKAGE_TAR" + echo "SRC_PACKAGE_TAR_GZ=$SRC_PACKAGE_TAR_GZ" + echo "SRC_PACKAGE_ZIP=$SRC_PACKAGE_ZIP" + echo "NPM_PACKAGE_NAME=$NPM_PACKAGE_NAME" + + - name: Verify Target Release Version + run: | + PACKAGE_VERSION=$(jq -r '.version' package.json) + if [ "$PACKAGE_VERSION" != "$TARGET_RELEASE_VERSION" ]; then + echo "Mismatch version detected between tag version ($TARGET_RELEASE_VERSION) and package version ($PACKAGE_VERSION)" + exit 1 + fi + + if [ -f "plugin.xml" ]; then + PLUGIN_VERSION=$(yq -p=xml -o=json '.plugin.+@version' plugin.xml | jq -r .) + if [ "$PLUGIN_VERSION" != "$TARGET_RELEASE_VERSION" ]; then + echo "Mismatch version detected between tag version ($TARGET_RELEASE_VERSION) and plugin version ($PLUGIN_VERSION)" + exit 1 + fi + fi + + - name: Generate "tgz" npm convenience package + run: |- + npm ci + NPM_PKG_NAME=$(npm pack --json | jq -r '.[0].filename') + mv ./.asf-release/$NPM_PKG_NAME ./.asf-release/${NPM_PACKAGE_NAME}.tgz + env: + TZ: UTC + + - name: Generate "tar" source package + run: |- + export SRC_LAST_COMMIT_EPOCH=$(git log -1 --format=%ct "$TAG_NAME") + + git archive \ + --prefix=$SRC_PACKAGE_NAME/ \ + --mtime=$SRC_LAST_COMMIT_EPOCH \ + -o ./.asf-release/${SRC_PACKAGE_TAR} \ + $TAG_NAME + env: + TZ: UTC + + - name: Generate "tar.gz" source archive + working-directory: ./.asf-release + run: |- + gzip -n -9 -c "$SRC_PACKAGE_TAR" > "$SRC_PACKAGE_TAR_GZ" + env: + TZ: UTC + + - name: Generate "zip" source archive + working-directory: ./.asf-release + run: |- + export ASF_RELEASE_DIR=$(pwd) + export TMP_DIR=$(mktemp -d) + + tar -xf "$SRC_PACKAGE_TAR" -C "$TMP_DIR" + ( + cd "$TMP_DIR" + find . -type f | LC_ALL=C sort | zip -X -q "$ASF_RELEASE_DIR/$SRC_PACKAGE_ZIP" -@ + ) + rm -rf $TMP_DIR + env: + TZ: UTC + + - name: Cleanup Process + working-directory: ./.asf-release + run: |- + rm -rf $SRC_PACKAGE_TAR + rm -rf .gitkeep + + - name: Create Sign and Checksum + working-directory: .asf-release + run: |- + for f in *.tar.gz *.tgz *.zip; do + [ -e "$f" ] || continue + echo "$CORDOVA_GPG_SECRET_KEY" | gpg --batch --import --import-options import-show + gpg --armor --detach-sign "$f" + sha512sum "$f" > "${f}.sha512" + done + env: + CORDOVA_GPG_SECRET_KEY: ${{ secrets.CORDOVA_GPG_SECRET_KEY }} + + - name: Upload to Apache Trusted Release (ATR) + uses: apache/tooling-actions/upload-to-atr@fa721a0b176d713807b574da721b96545b587eea + with: + project: ${{ env.REPO_NAME }} + version: ${{ env.TARGET_RELEASE_VERSION }} + src: .asf-release diff --git a/.github/workflows/release-audit.yml b/.github/workflows/release-audit.yml new file mode 100644 index 00000000..6bceca2c --- /dev/null +++ b/.github/workflows/release-audit.yml @@ -0,0 +1,58 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: Release Auditing + +on: + push: + branches-ignore: + - 'dependabot/**' + pull_request: + branches: + - '*' + +permissions: + contents: read + +jobs: + test: + name: Audit Licenses + runs-on: ubuntu-latest + steps: + # Checkout project + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + fetch-depth: 1 + + # Check license headers + - uses: erisu/apache-rat-action@30c94d10ed21e6f6fd5590dc5c158f58cae7a0dd # v3.0.0 + + # Setup environment with node + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 24 + + # Install node packages + - name: npm install packages + run: npm ci + + # Check node package licenses + - uses: erisu/license-checker-action@04511f4c052b5773f11e1c65b42cda88235c62ae # v2.1.0 + with: + license-config: 'licence_checker.yml' + include-asf-category-a: true diff --git a/.gitignore b/.gitignore index 796bd5be..54c853c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + node_modules/* .DS_Store npm-debug.log -package-lock.json +coverage +.nyc_output +lcov.info + +# ASF release workspace +.asf-release/ +!.asf-release/.gitkeep diff --git a/.npmignore b/.npmignore index 65e3ba2e..58ea5484 100644 --- a/.npmignore +++ b/.npmignore @@ -1 +1,25 @@ -test/ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +.* +coverage +test +eslint.config.js +licence_checker.yml + +# ASF release workspace +.asf-release/ diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..6f982f74 --- /dev/null +++ b/.npmrc @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +registry=https://registry.npmjs.org + +# ASF release settings +git-tag-version=false +preid=dev +pack-destination=./.asf-release diff --git a/.rat-excludes b/.rat-excludes new file mode 100644 index 00000000..3f180d6d --- /dev/null +++ b/.rat-excludes @@ -0,0 +1,22 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +.git/ +coverage/ +node_modules/ +test/parser/projects/**/*.pbxproj +lcov.info diff --git a/.ratignore b/.ratignore deleted file mode 100644 index eecfa9a4..00000000 --- a/.ratignore +++ /dev/null @@ -1,2 +0,0 @@ -fixtures -*.pbxproj diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 44b04f9e..00000000 --- a/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -language: node_js -sudo: false - -git: - depth: 10 - -node_js: - - 6 - - 8 - - 10 - - 12 - -os: - - linux - - osx - -install: - - nvm --version - - node --version - - npm --version - - npm install - -script: - - npm test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..94d5e9a7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,37 @@ + + +# Contributing to Apache Cordova + +Anyone can contribute to Cordova. And we need your contributions. + +There are multiple ways to contribute: report bugs, improve the docs, and +contribute code. + +For instructions on this, start with the +[contribution overview](http://cordova.apache.org/contribute/). + +The details are explained there, but the important items are: + - Check for Github issues that corresponds to your contribution and link or create them if necessary. + - Run the tests so your patch doesn't break existing functionality. + +We look forward to your contributions! + diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 00000000..50997d9a --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,105 @@ + + +# Development + +## Setup + +1. Install npm dependencies. + + ```bash + npm install + ``` + +## Updating the parser + +If there's a problem parsing, you will want to edit the grammar under `lib/parser/pbxproj.pegjs`. + +Tests under the `test/parser` directory will compile the parser from the grammar. The other tests will use the prebuilt parser (`lib/parser/pbxproj.js`). + +To build the parser js file after editing the grammar, run: + +```bash +npm run build +``` + +## Unit Testing + +Our projects include unit tests, which can be run with: + +```bash +npm test +``` + +## Linting + +During development, you should run the linter to ensure the code follows our coding standards: + +```bash +npm run lint +``` + +> [!NOTE] +> Running `npm test` will also execute the linter before running the tests. + +### Fixing Lint Issues + +In many cases, lint warnings can be fixed automatically with: + +```bash +npm run lint:fix +``` + +If an issue cannot be resolved automatically, it will require manual review and correction. + +## Building from Source + +1. **Clone the repository** locally. + +2. **Change to the repository directory.** + +3. **Install dependencies:** + + ```bash + npm install + ``` + + Installs all production and development dependencies required for using and developing the package. + +4. **Update sub-dependencies:** + + ```bash + npm update + ``` + + Over time, `package-lock.json` can become stale and may trigger audit warnings. `npm update` refreshes dependencies within the pinned versions. + + Under normal circumstances, users install the published package from the npm registry, which does **not** include its own `package-lock.json`. Instead, npm resolves and installs the latest compatible dependency versions at install time, which may result in no audit warnings. + + Running `npm update` locally can provide a more accurate representation of current npm audit results for the project. + +5. **Generate a tarball:** + + ```bash + npm pack + ``` + + Creates a `.tgz` tarball file in the `.asf-release` directory. diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..d42a3ea4 --- /dev/null +++ b/NOTICE @@ -0,0 +1,5 @@ +Apache Cordova +Copyright 2012-2020 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md index 814a221d..d81fe0a2 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,12 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the +# KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # @@ -21,8 +21,12 @@ # cordova-node-xcode -[![NPM](https://nodei.co/npm/xcode.png?compact=true)](https://nodei.co/npm/xcode/) -[![Build Status](https://travis-ci.org/apache/cordova-node-xcode.svg?branch=master)](https://travis-ci.org/apache/cordova-node-xcode) +[![npm - Latest](https://img.shields.io/npm/v/xcode/latest?label=Latest%20Release%20(npm))](https://npmjs.com/package/xcode) +[![GitHub](https://img.shields.io/github/package-json/v/apache/cordova-node-xcode?label=Development%20(Git))](https://github.com/apache/cordova-node-xcode) + +[![GitHub - Node Workflow](https://github.com/apache/cordova-node-xcode/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/apache/cordova-node-xcode/actions/workflows/ci.yml?query=branch%3Amaster) +[![GitHub - Release Audit Workflow](https://github.com/apache/cordova-node-xcode/actions/workflows/release-audit.yml/badge.svg?branch=master)](https://github.com/apache/cordova-node-xcode/actions/workflows/release-audit.yml?query=branch%3Amaster) +[![Code Coverage](https://codecov.io/github/apache/cordova-node-xcode/coverage.svg?branch=master)](https://codecov.io/github/apache/cordova-node-xcode?branch=master) Parser utility for xcodeproj project files @@ -33,39 +37,23 @@ based on donated code from [alunny / node-xcode](https://github.com/alunny/node- ## Example ```js -// API is a bit wonky right now -var xcode = require('xcode'), - fs = require('fs'), - projectPath = 'myproject.xcodeproj/project.pbxproj', - myProj = xcode.project(projectPath); +const fs = require('node:fs'); +const xcode = require('xcode'); + +// Path to the Xcode project's project.pbxproj file. +const projectPath = 'myproject.xcodeproj/project.pbxproj'; +// Create a PBXProject instance for the project. +const myProj = xcode.project(projectPath); -// parsing is async, in a different process +// Parse the project file asynchronously before making changes. myProj.parse(function (err) { myProj.addHeaderFile('foo.h'); myProj.addSourceFile('foo.m'); myProj.addFramework('FooKit.framework'); + // Write the updated project back to disk. fs.writeFileSync(projectPath, myProj.writeSync()); - console.log('new project written'); + + console.log('New project written'); }); ``` - -## Working on the parser - -If there's a problem parsing, you will want to edit the grammar under -`lib/parser/pbxproj.pegjs`. You can test it online with the PEGjs online thingy -at https://pegjs.org/online - I have had some mixed results though. - -Tests under the `test/parser` directory will compile the parser from the -grammar. Other tests will use the prebuilt parser (`lib/parser/pbxproj.js`). - -To rebuild the parser js file after editing the grammar, run: - - npm run pegjs - -(and be sure to restore the Apache license notice in -`lib/parser/pbxproj.js` before committing) - -## License - -Apache V2 diff --git a/RELEASENOTES.md b/RELEASENOTES.md index ac2916df..021b0b82 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -8,18 +8,38 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the +# KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # --> + # Cordova-node-xcode Release Notes +### 3.0.1 (May 15, 2020) + +* [GH-109](https://github.com/apache/cordova-node-xcode/pull/109) Add targetName to paramter to getBuildProperty + +### 3.0.0 (Apr 09, 2020) + +* node-xcode-3.0.0 Added NOTICE for release +* [GH-107](https://github.com/apache/cordova-node-xcode/pull/107) doc(README): fix CI badge url +* [GH-106](https://github.com/apache/cordova-node-xcode/pull/106) Update build property by `targetname` +* [GH-79](https://github.com/apache/cordova-node-xcode/pull/79) feat: add new optional paramter to `pbxProject.addTarget` +* [GH-96](https://github.com/apache/cordova-node-xcode/pull/96) ci: switch travis ci for github actions +* [GH-94](https://github.com/apache/cordova-node-xcode/pull/94) breaking(npm): bump dependencies + * `simple-plist@^1.1.0` + * `uuid@^7.0.3` +* [GH-93](https://github.com/apache/cordova-node-xcode/pull/93) chore(npm): use short notation for repo & bugs +* [GH-90](https://github.com/apache/cordova-node-xcode/pull/90) ci(travis): removes Node.js v6 and v8 from testing +* [GH-92](https://github.com/apache/cordova-node-xcode/pull/92) chore: bump node requirement (`>=10`) +* [GH-89](https://github.com/apache/cordova-node-xcode/pull/89) chore(npm): improve ignore list + ### 2.1.0 (December 12, 2019) * Add target test coverage ([#82](https://github.com/apache/cordova-node-xcode/pull/82)) * ensure coverage for addTargetDependency with invalid input ([#81](https://github.com/apache/cordova-node-xcode/pull/81)) diff --git a/bin/generate-pbxproj-parser.js b/bin/generate-pbxproj-parser.js new file mode 100644 index 00000000..70581b3b --- /dev/null +++ b/bin/generate-pbxproj-parser.js @@ -0,0 +1,60 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const fs = require('node:fs'); +const path = require('node:path'); +const peg = require('pegjs'); + +const ROOT_DIR = path.join(__dirname, '..'); +const parserDir = path.join(ROOT_DIR, 'lib/parser'); + +// Path to grammar file +const grammarFilePath = path.join(parserDir, 'pbxproj.pegjs'); +// Path to where the parser file is outputted +const outputFilePath = path.join(parserDir, 'pbxproj.js'); + +// Fetches the grammar file content and builds the output data. +const grammarData = fs.readFileSync(grammarFilePath, 'utf8'); +const outputData = peg.generate(grammarData, { + output: 'source', + format: 'commonjs' +}); + +const asfLicenseHeader = `/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +`; + +// Append the Apache license header to the top of the built file. +fs.writeFileSync(outputFilePath, `${asfLicenseHeader}${outputData}`); diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..14530251 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,33 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { defineConfig, globalIgnores } = require('eslint/config'); +const nodeConfig = require('@cordova/eslint-config/node'); +const nodeTestConfig = require('@cordova/eslint-config/node-tests'); + +module.exports = defineConfig([ + globalIgnores([ + 'lib/parser/pbxproj.js' + ]), + ...nodeConfig, + ...nodeTestConfig.map(config => ({ + files: ['test/**/*.js'], + ...config + })) +]); diff --git a/index.js b/index.js index 4fe8416b..dee3fc47 100644 --- a/index.js +++ b/index.js @@ -1,18 +1,20 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -exports.project = require('./lib/pbxProject') + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +exports.project = require('./lib/pbxProject'); diff --git a/lib/parseJob.js b/lib/parseJob.js index 4e34eb2f..5d8f5271 100644 --- a/lib/parseJob.js +++ b/lib/parseJob.js @@ -1,26 +1,29 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ // parsing is slow and blocking right now // so we do it in a separate process -var fs = require('fs'), - parser = require('./parser/pbxproj'), - path = process.argv[2], - fileContents, obj; +const fs = require('fs'); +const parser = require('./parser/pbxproj'); +const path = process.argv[2]; +let fileContents; +let obj; try { fileContents = fs.readFileSync(path, 'utf-8'); diff --git a/lib/parser/pbxproj.js b/lib/parser/pbxproj.js index 81ae25f2..f42f18e3 100644 --- a/lib/parser/pbxproj.js +++ b/lib/parser/pbxproj.js @@ -1,20 +1,21 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ /* * Generated by PEG.js 0.10.0. * @@ -176,9 +177,47 @@ function peg$parse(input, options) { peg$c6 = function() { return Object.create(null) }, peg$c7 = function(list) { var returnObject = list[0][0]; - for(var i = 1; i < list.length; i++){ + + for (var i = 1; i < list.length; i++) { var another = list[i][0]; - returnObject = Object.assign(returnObject, another); + + /* + * Ensure previously parsed section entries are not lost + * + * Example: + * + * If "returnObject" contains: + * + * { + * PBXTargetDependency: { + * 'A': {}, + * 'A_comment': 'PBXTargetDependency' + * } + * } + * + * And "another" contains: + * + * { + * PBXTargetDependency: { + * 'B': {}, + * 'B_comment': 'PBXTargetDependency' + * } + * } + * + * Using "Object.assign(returnObject, another)" would lose + * "A" as it would replace the entire PBXTargetDependency. + * + * Instead, we will merge each top-level property of the + * objects, if it exists and is an object else add. + */ + for (var key in another) { + returnObject[key] = ( + returnObject[key] && + another[key] && + typeof returnObject[key] === 'object' && + typeof another[key] === 'object' + ) ? Object.assign(returnObject[key], another[key]) : another[key]; + } } return returnObject; }, diff --git a/lib/parser/pbxproj.pegjs b/lib/parser/pbxproj.pegjs index 66699e09..6c8bec6c 100644 --- a/lib/parser/pbxproj.pegjs +++ b/lib/parser/pbxproj.pegjs @@ -1,31 +1,21 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -{ - function merge_obj(obj, secondObj) { - if (!obj) - return secondObj; - - for(var i in secondObj) - obj[i] = merge_obj(obj[i], secondObj[i]); - - return obj; - } -} +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ /* * Project: point of entry from pbxproj file @@ -58,9 +48,47 @@ AssignmentList = _ list:((a:Assignment / d:DelimitedSection) _)+ { var returnObject = list[0][0]; - for(var i = 1; i < list.length; i++){ + + for (var i = 1; i < list.length; i++) { var another = list[i][0]; - returnObject = merge_obj(returnObject, another); + + /* + * Ensure previously parsed section entries are not lost + * + * Example: + * + * If "returnObject" contains: + * + * { + * PBXTargetDependency: { + * 'A': {}, + * 'A_comment': 'PBXTargetDependency' + * } + * } + * + * And "another" contains: + * + * { + * PBXTargetDependency: { + * 'B': {}, + * 'B_comment': 'PBXTargetDependency' + * } + * } + * + * Using "Object.assign(returnObject, another)" would lose + * "A" as it would replace the entire PBXTargetDependency. + * + * Instead, we will merge each top-level property of the + * objects, if it exists and is an object else add. + */ + for (var key in another) { + returnObject[key] = ( + returnObject[key] && + another[key] && + typeof returnObject[key] === 'object' && + typeof another[key] === 'object' + ) ? Object.assign(returnObject[key], another[key]) : another[key]; + } } return returnObject; } diff --git a/lib/pbxFile.js b/lib/pbxFile.js index 9553bfb5..59dcef9b 100644 --- a/lib/pbxFile.js +++ b/lib/pbxFile.js @@ -1,94 +1,93 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var path = require('path'), - util = require('util'); - -var DEFAULT_SOURCETREE = '""', - DEFAULT_PRODUCT_SOURCETREE = 'BUILT_PRODUCTS_DIR', - DEFAULT_FILEENCODING = 4, - DEFAULT_GROUP = 'Resources', - DEFAULT_FILETYPE = 'unknown'; - -var FILETYPE_BY_EXTENSION = { - a: 'archive.ar', - app: 'wrapper.application', - appex: 'wrapper.app-extension', - bundle: 'wrapper.plug-in', - dylib: 'compiled.mach-o.dylib', - framework: 'wrapper.framework', - h: 'sourcecode.c.h', - m: 'sourcecode.c.objc', - markdown: 'text', - mdimporter: 'wrapper.cfbundle', - octest: 'wrapper.cfbundle', - pch: 'sourcecode.c.h', - plist: 'text.plist.xml', - sh: 'text.script.sh', - swift: 'sourcecode.swift', - tbd: 'sourcecode.text-based-dylib-definition', - xcassets: 'folder.assetcatalog', - xcconfig: 'text.xcconfig', - xcdatamodel: 'wrapper.xcdatamodel', - xcodeproj: 'wrapper.pb-project', - xctest: 'wrapper.cfbundle', - xib: 'file.xib', - strings: 'text.plist.strings' - }, - GROUP_BY_FILETYPE = { - 'archive.ar': 'Frameworks', - 'compiled.mach-o.dylib': 'Frameworks', - 'sourcecode.text-based-dylib-definition': 'Frameworks', - 'wrapper.framework': 'Frameworks', - 'embedded.framework': 'Embed Frameworks', - 'sourcecode.c.h': 'Resources', - 'sourcecode.c.objc': 'Sources', - 'sourcecode.swift': 'Sources' - }, - PATH_BY_FILETYPE = { - 'compiled.mach-o.dylib': 'usr/lib/', - 'sourcecode.text-based-dylib-definition': 'usr/lib/', - 'wrapper.framework': 'System/Library/Frameworks/' - }, - SOURCETREE_BY_FILETYPE = { - 'compiled.mach-o.dylib': 'SDKROOT', - 'sourcecode.text-based-dylib-definition': 'SDKROOT', - 'wrapper.framework': 'SDKROOT' - }, - ENCODING_BY_FILETYPE = { - 'sourcecode.c.h': 4, - 'sourcecode.c.h': 4, - 'sourcecode.c.objc': 4, - 'sourcecode.swift': 4, - 'text': 4, - 'text.plist.xml': 4, - 'text.script.sh': 4, - 'text.xcconfig': 4, - 'text.plist.strings': 4 - }; - - -function unquoted(text){ - return text == null ? '' : text.replace (/(^")|("$)/g, '') +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const path = require('path'); +const util = require('util'); + +const DEFAULT_SOURCETREE = '""'; +const DEFAULT_PRODUCT_SOURCETREE = 'BUILT_PRODUCTS_DIR'; +const DEFAULT_GROUP = 'Resources'; +const DEFAULT_FILETYPE = 'unknown'; + +const FILETYPE_BY_EXTENSION = { + a: 'archive.ar', + app: 'wrapper.application', + appex: 'wrapper.app-extension', + bundle: 'wrapper.plug-in', + dylib: 'compiled.mach-o.dylib', + framework: 'wrapper.framework', + h: 'sourcecode.c.h', + m: 'sourcecode.c.objc', + markdown: 'text', + mdimporter: 'wrapper.cfbundle', + octest: 'wrapper.cfbundle', + pch: 'sourcecode.c.h', + plist: 'text.plist.xml', + sh: 'text.script.sh', + swift: 'sourcecode.swift', + tbd: 'sourcecode.text-based-dylib-definition', + xcassets: 'folder.assetcatalog', + xcconfig: 'text.xcconfig', + xcdatamodel: 'wrapper.xcdatamodel', + xcodeproj: 'wrapper.pb-project', + xctest: 'wrapper.cfbundle', + xib: 'file.xib', + strings: 'text.plist.strings' +}; +const GROUP_BY_FILETYPE = { + 'archive.ar': 'Frameworks', + 'compiled.mach-o.dylib': 'Frameworks', + 'sourcecode.text-based-dylib-definition': 'Frameworks', + 'wrapper.framework': 'Frameworks', + 'embedded.framework': 'Embed Frameworks', + 'sourcecode.c.h': 'Resources', + 'sourcecode.c.objc': 'Sources', + 'sourcecode.swift': 'Sources' +}; +const PATH_BY_FILETYPE = { + 'compiled.mach-o.dylib': 'usr/lib/', + 'sourcecode.text-based-dylib-definition': 'usr/lib/', + 'wrapper.framework': 'System/Library/Frameworks/' +}; +const SOURCETREE_BY_FILETYPE = { + 'compiled.mach-o.dylib': 'SDKROOT', + 'sourcecode.text-based-dylib-definition': 'SDKROOT', + 'wrapper.framework': 'SDKROOT' +}; +const ENCODING_BY_FILETYPE = { + 'sourcecode.c.h': 4, + 'sourcecode.c.objc': 4, + 'sourcecode.swift': 4, + text: 4, + 'text.plist.xml': 4, + 'text.script.sh': 4, + 'text.xcconfig': 4, + 'text.plist.strings': 4 +}; + +function unquoted (text) { + return text == null ? '' : text.replace(/(^")|("$)/g, ''); } -function detectType(filePath) { - var extension = path.extname(filePath).substring(1), - filetype = FILETYPE_BY_EXTENSION[unquoted(extension)]; +function detectType (filePath) { + const extension = path.extname(filePath).substring(1); + const filetype = FILETYPE_BY_EXTENSION[unquoted(extension)]; if (!filetype) { return DEFAULT_FILETYPE; @@ -97,31 +96,31 @@ function detectType(filePath) { return filetype; } -function defaultExtension(fileRef) { - var filetype = fileRef.lastKnownFileType && fileRef.lastKnownFileType != DEFAULT_FILETYPE ? - fileRef.lastKnownFileType : fileRef.explicitFileType; +function defaultExtension (fileRef) { + const filetype = fileRef.lastKnownFileType && fileRef.lastKnownFileType !== DEFAULT_FILETYPE + ? fileRef.lastKnownFileType + : fileRef.explicitFileType; - for(var extension in FILETYPE_BY_EXTENSION) { - if(FILETYPE_BY_EXTENSION.hasOwnProperty(unquoted(extension)) ) { - if(FILETYPE_BY_EXTENSION[unquoted(extension)] === unquoted(filetype) ) - return extension; + for (const extension in FILETYPE_BY_EXTENSION) { + if (Object.prototype.hasOwnProperty.call(FILETYPE_BY_EXTENSION, unquoted(extension))) { + if (FILETYPE_BY_EXTENSION[unquoted(extension)] === unquoted(filetype)) { return extension; } } } } -function defaultEncoding(fileRef) { - var filetype = fileRef.lastKnownFileType || fileRef.explicitFileType, - encoding = ENCODING_BY_FILETYPE[unquoted(filetype)]; +function defaultEncoding (fileRef) { + const filetype = fileRef.lastKnownFileType || fileRef.explicitFileType; + const encoding = ENCODING_BY_FILETYPE[unquoted(filetype)]; if (encoding) { return encoding; } } -function detectGroup(fileRef, opt) { - var extension = path.extname(fileRef.basename).substring(1), - filetype = fileRef.lastKnownFileType || fileRef.explicitFileType, - groupName = GROUP_BY_FILETYPE[unquoted(filetype)]; +function detectGroup (fileRef, opt) { + const extension = path.extname(fileRef.basename).substring(1); + const filetype = fileRef.lastKnownFileType || fileRef.explicitFileType; + const groupName = GROUP_BY_FILETYPE[unquoted(filetype)]; if (extension === 'xcdatamodeld') { return 'Sources'; @@ -138,10 +137,9 @@ function detectGroup(fileRef, opt) { return groupName; } -function detectSourcetree(fileRef) { - - var filetype = fileRef.lastKnownFileType || fileRef.explicitFileType, - sourcetree = SOURCETREE_BY_FILETYPE[unquoted(filetype)]; +function detectSourcetree (fileRef) { + const filetype = fileRef.lastKnownFileType || fileRef.explicitFileType; + const sourcetree = SOURCETREE_BY_FILETYPE[unquoted(filetype)]; if (fileRef.explicitFileType) { return DEFAULT_PRODUCT_SOURCETREE; @@ -158,40 +156,30 @@ function detectSourcetree(fileRef) { return sourcetree; } -function defaultPath(fileRef, filePath) { - var filetype = fileRef.lastKnownFileType || fileRef.explicitFileType, - defaultPath = PATH_BY_FILETYPE[unquoted(filetype)]; +function defaultPath (fileRef, filePath) { + const filetype = fileRef.lastKnownFileType || fileRef.explicitFileType; + const defaultPath = PATH_BY_FILETYPE[unquoted(filetype)]; if (fileRef.customFramework) { return filePath; } if (defaultPath) { - return path.join(defaultPath, path.basename(filePath)); + return path.posix.join(defaultPath, path.basename(filePath)); } return filePath; } -function defaultGroup(fileRef) { - var groupName = GROUP_BY_FILETYPE[fileRef.lastKnownFileType]; - - if (!groupName) { - return DEFAULT_GROUP; - } - - return defaultGroup; -} - -function pbxFile(filepath, opt) { - var opt = opt || {}; +function pbxFile (filepath, opt) { + opt = opt || {}; this.basename = path.basename(filepath); this.lastKnownFileType = opt.lastKnownFileType || detectType(filepath); this.group = detectGroup(this, opt); // for custom frameworks - if (opt.customFramework == true) { + if (opt.customFramework === true) { this.customFramework = true; this.dirname = path.dirname(filepath).replace(/\\/g, '/'); } @@ -212,21 +200,17 @@ function pbxFile(filepath, opt) { this.sourceTree = opt.sourceTree || detectSourcetree(this); this.includeInIndex = 0; - if (opt.weak && opt.weak === true) - this.settings = { ATTRIBUTES: ['Weak'] }; + if (opt.weak && opt.weak === true) { this.settings = { ATTRIBUTES: ['Weak'] }; } if (opt.compilerFlags) { - if (!this.settings) - this.settings = {}; + if (!this.settings) { this.settings = {}; } this.settings.COMPILER_FLAGS = util.format('"%s"', opt.compilerFlags); } if (opt.embed && opt.sign) { - if (!this.settings) - this.settings = {}; - if (!this.settings.ATTRIBUTES) - this.settings.ATTRIBUTES = []; - this.settings.ATTRIBUTES.push('CodeSignOnCopy'); + if (!this.settings) { this.settings = {}; } + if (!this.settings.ATTRIBUTES) { this.settings.ATTRIBUTES = []; } + this.settings.ATTRIBUTES.push('CodeSignOnCopy'); } } diff --git a/lib/pbxProject.js b/lib/pbxProject.js index 3097678c..07fc0629 100644 --- a/lib/pbxProject.js +++ b/lib/pbxProject.js @@ -1,51 +1,111 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const util = require('util'); +const f = util.format; +const EventEmitter = require('events').EventEmitter; +const path = require('path'); +const crypto = require('crypto'); +const fork = require('child_process').fork; +const PBXWriter = require('./pbxWriter'); +const PBXFile = require('./pbxFile'); +const fs = require('fs'); +const parser = require('./parser/pbxproj'); +const plist = require('simple-plist'); +const COMMENT_KEY = /_comment$/; + +// MARK: Start of Typings + +/** + * A list of known build phase types. + * @typedef {'PBXCopyFilesBuildPhase' | + * 'PBXResourcesBuildPhase' | + * 'PBXFrameworksBuildPhase' | + * 'PBXHeadersBuildPhase' | + * 'PBXShellScriptBuildPhase' | + * 'PBXSourcesBuildPhase' + * } BuildPhaseType + */ + +/** + * The result object returned when adding a build phase. + * @typedef {object} AddBuildPhaseResults + * @property {string} uuid Build Phase UUID + * @property {object} buildPhase Build Phase object + */ + /** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. + * A list of valid target types used for copy files build configurations. + * @typedef {'application' + * | 'app_extension' + * | 'bundle' + * | 'command_line_tool' + * | 'dynamic_library' + * | 'framework' + * | 'frameworks' + * | 'static_library' + * | 'unit_test_bundle' + * | 'watch_app' + * | 'watch2_app' + * | 'watch_extension' + * | 'watch2_extension' + * } CopyFilesTargetType */ -var util = require('util'), - f = util.format, - EventEmitter = require('events').EventEmitter, - path = require('path'), - uuid = require('uuid'), - fork = require('child_process').fork, - pbxWriter = require('./pbxWriter'), - pbxFile = require('./pbxFile'), - fs = require('fs'), - parser = require('./parser/pbxproj'), - plist = require('simple-plist'), - COMMENT_KEY = /_comment$/ - -function pbxProject(filename) { - if (!(this instanceof pbxProject)) - return new pbxProject(filename); - - this.filepath = path.resolve(filename) +/** + * Options used when adding a PBXShellScriptBuildPhase. + * @typedef {object} ShellScriptOptions + * @property {string[]} inputPaths input paths + * @property {string[]} outputPaths output Paths + * @property {string} shellPath shell paths + * @property {0 | 1} runOnlyForDeploymentPostprocessing run script for install builds only + * @property {1} [alwaysOutOfDate] disables dependency analysis when set to true + */ + +// MARK: End of Typings + +// MARK: Start of Internals + +/** + * A list of restricted object keys. + */ +const RESTRICTED_OBJECT_KEYS = new Set(['__proto__', 'prototype', 'constructor']); + +// MARK: End of Internals + +function PBXProject (filename) { + if (!(this instanceof PBXProject)) { return new PBXProject(filename); } + + this.filepath = path.resolve(filename); } -util.inherits(pbxProject, EventEmitter) +util.inherits(PBXProject, EventEmitter); -pbxProject.prototype.parse = function(cb) { - var worker = fork(__dirname + '/parseJob.js', [this.filepath]) +PBXProject.prototype.parse = function (cb) { + const worker = fork(path.join(__dirname, 'parseJob.js'), [this.filepath]); - worker.on('message', function(msg) { - if (msg.name == 'SyntaxError' || msg.code) { + worker.on('message', function (msg) { + if (msg.name === 'SyntaxError' || msg.code) { this.emit('error', msg); } else { this.hash = msg; - this.emit('end', null, msg) + this.emit('end', null, msg); } }.bind(this)); @@ -55,52 +115,52 @@ pbxProject.prototype.parse = function(cb) { } return this; -} +}; -pbxProject.prototype.parseSync = function() { - var file_contents = fs.readFileSync(this.filepath, 'utf-8'); +PBXProject.prototype.parseSync = function () { + const file_contents = fs.readFileSync(this.filepath, 'utf-8'); this.hash = parser.parse(file_contents); return this; -} +}; -pbxProject.prototype.writeSync = function(options) { - this.writer = new pbxWriter(this.hash, options); +PBXProject.prototype.writeSync = function (options) { + this.writer = new PBXWriter(this.hash, options); return this.writer.writeSync(); -} +}; -pbxProject.prototype.allUuids = function() { - var sections = this.hash.project.objects, - uuids = [], - section; +PBXProject.prototype.allUuids = function () { + const sections = this.hash.project.objects; + let uuids = []; + let section; - for (key in sections) { - section = sections[key] - uuids = uuids.concat(Object.keys(section)) + for (const key in sections) { + section = sections[key]; + uuids = uuids.concat(Object.keys(section)); } - uuids = uuids.filter(function(str) { - return !COMMENT_KEY.test(str) && str.length == 24; + uuids = uuids.filter(function (str) { + return !COMMENT_KEY.test(str) && str.length === 24; }); return uuids; -} +}; -pbxProject.prototype.generateUuid = function() { - var id = uuid.v4() +PBXProject.prototype.generateUuid = function () { + const id = crypto.randomUUID() .replace(/-/g, '') .substr(0, 24) - .toUpperCase() + .toUpperCase(); if (this.allUuids().indexOf(id) >= 0) { return this.generateUuid(); } else { return id; } -} +}; -pbxProject.prototype.addPluginFile = function(path, opt) { - var file = new pbxFile(path, opt); +PBXProject.prototype.addPluginFile = function (path, opt) { + const file = new PBXFile(path, opt); file.plugin = true; // durr correctForPluginsPath(file, this); @@ -110,24 +170,24 @@ pbxProject.prototype.addPluginFile = function(path, opt) { file.fileRef = this.generateUuid(); - this.addToPbxFileReferenceSection(file); // PBXFileReference - this.addToPluginsPbxGroup(file); // PBXGroup + this.addToPbxFileReferenceSection(file); // PBXFileReference + this.addToPluginsPbxGroup(file); // PBXGroup return file; -} +}; -pbxProject.prototype.removePluginFile = function(path, opt) { - var file = new pbxFile(path, opt); +PBXProject.prototype.removePluginFile = function (path, opt) { + const file = new PBXFile(path, opt); correctForPluginsPath(file, this); - this.removeFromPbxFileReferenceSection(file); // PBXFileReference - this.removeFromPluginsPbxGroup(file); // PBXGroup + this.removeFromPbxFileReferenceSection(file); // PBXFileReference + this.removeFromPluginsPbxGroup(file); // PBXGroup return file; -} +}; -pbxProject.prototype.addProductFile = function(targetPath, opt) { - var file = new pbxFile(targetPath, opt); +PBXProject.prototype.addProductFile = function (targetPath, opt) { + const file = new PBXFile(targetPath, opt); file.includeInIndex = 0; file.fileRef = this.generateUuid(); @@ -137,18 +197,18 @@ pbxProject.prototype.addProductFile = function(targetPath, opt) { file.path = file.basename; this.addToPbxFileReferenceSection(file); - this.addToProductsPbxGroup(file); // PBXGroup + this.addToProductsPbxGroup(file); // PBXGroup return file; -} +}; -pbxProject.prototype.removeProductFile = function(path, opt) { - var file = new pbxFile(path, opt); +PBXProject.prototype.removeProductFile = function (path, opt) { + const file = new PBXFile(path, opt); - this.removeFromProductsPbxGroup(file); // PBXGroup + this.removeFromProductsPbxGroup(file); // PBXGroup return file; -} +}; /** * @@ -157,12 +217,11 @@ pbxProject.prototype.removeProductFile = function(path, opt) { * @param group {String} group key * @returns {Object} file; see pbxFile */ -pbxProject.prototype.addSourceFile = function (path, opt, group) { - var file; +PBXProject.prototype.addSourceFile = function (path, opt, group) { + let file; if (group) { file = this.addFile(path, group, opt); - } - else { + } else { file = this.addPluginFile(path, opt); } @@ -171,11 +230,11 @@ pbxProject.prototype.addSourceFile = function (path, opt, group) { file.target = opt ? opt.target : undefined; file.uuid = this.generateUuid(); - this.addToPbxBuildFileSection(file); // PBXBuildFile - this.addToPbxSourcesBuildPhase(file); // PBXSourcesBuildPhase + this.addToPbxBuildFileSection(file); // PBXBuildFile + this.addToPbxSourcesBuildPhase(file); // PBXSourcesBuildPhase return file; -} +}; /** * @@ -184,20 +243,19 @@ pbxProject.prototype.addSourceFile = function (path, opt, group) { * @param group {String} group key * @returns {Object} file; see pbxFile */ -pbxProject.prototype.removeSourceFile = function (path, opt, group) { - var file; +PBXProject.prototype.removeSourceFile = function (path, opt, group) { + let file; if (group) { file = this.removeFile(path, group, opt); - } - else { + } else { file = this.removePluginFile(path, opt); } file.target = opt ? opt.target : undefined; - this.removeFromPbxBuildFileSection(file); // PBXBuildFile - this.removeFromPbxSourcesBuildPhase(file); // PBXSourcesBuildPhase + this.removeFromPbxBuildFileSection(file); // PBXBuildFile + this.removeFromPbxSourcesBuildPhase(file); // PBXSourcesBuildPhase return file; -} +}; /** * @@ -206,14 +264,13 @@ pbxProject.prototype.removeSourceFile = function (path, opt, group) { * @param group {String} group key * @returns {Object} file; see pbxFile */ -pbxProject.prototype.addHeaderFile = function (path, opt, group) { +PBXProject.prototype.addHeaderFile = function (path, opt, group) { if (group) { return this.addFile(path, group, opt); - } - else { + } else { return this.addPluginFile(path, opt); } -} +}; /** * @@ -222,14 +279,13 @@ pbxProject.prototype.addHeaderFile = function (path, opt, group) { * @param group {String} group key * @returns {Object} file; see pbxFile */ -pbxProject.prototype.removeHeaderFile = function (path, opt, group) { +PBXProject.prototype.removeHeaderFile = function (path, opt, group) { if (group) { return this.removeFile(path, group, opt); - } - else { + } else { return this.removePluginFile(path, opt); } -} +}; /** * @@ -238,16 +294,16 @@ pbxProject.prototype.removeHeaderFile = function (path, opt, group) { * @param group {String} group key * @returns {Object} file; see pbxFile */ -pbxProject.prototype.addResourceFile = function(path, opt, group) { +PBXProject.prototype.addResourceFile = function (path, opt, group) { opt = opt || {}; - var file; + let file; if (opt.plugin) { file = this.addPluginFile(path, opt); if (!file) return false; } else { - file = new pbxFile(path, opt); + file = new PBXFile(path, opt); if (this.hasFile(file.path)) return false; } @@ -260,28 +316,25 @@ pbxProject.prototype.addResourceFile = function(path, opt, group) { } if (!opt.variantGroup) { - this.addToPbxBuildFileSection(file); // PBXBuildFile - this.addToPbxResourcesBuildPhase(file); // PBXResourcesBuildPhase + this.addToPbxBuildFileSection(file); // PBXBuildFile + this.addToPbxResourcesBuildPhase(file); // PBXResourcesBuildPhase } if (!opt.plugin) { - this.addToPbxFileReferenceSection(file); // PBXFileReference + this.addToPbxFileReferenceSection(file); // PBXFileReference if (group) { if (this.getPBXGroupByKey(group)) { - this.addToPbxGroup(file, group); //Group other than Resources (i.e. 'splash') - } - else if (this.getPBXVariantGroupByKey(group)) { - this.addToPbxVariantGroup(file, group); // PBXVariantGroup + this.addToPbxGroup(file, group); // Group other than Resources (i.e. 'splash') + } else if (this.getPBXVariantGroupByKey(group)) { + this.addToPbxVariantGroup(file, group); // PBXVariantGroup } + } else { + this.addToResourcesPbxGroup(file); // PBXGroup } - else { - this.addToResourcesPbxGroup(file); // PBXGroup - } - } return file; -} +}; /** * @@ -290,40 +343,38 @@ pbxProject.prototype.addResourceFile = function(path, opt, group) { * @param group {String} group key * @returns {Object} file; see pbxFile */ -pbxProject.prototype.removeResourceFile = function(path, opt, group) { - var file = new pbxFile(path, opt); +PBXProject.prototype.removeResourceFile = function (path, opt, group) { + const file = new PBXFile(path, opt); file.target = opt ? opt.target : undefined; correctForResourcesPath(file, this); - this.removeFromPbxBuildFileSection(file); // PBXBuildFile - this.removeFromPbxFileReferenceSection(file); // PBXFileReference + this.removeFromPbxBuildFileSection(file); // PBXBuildFile + this.removeFromPbxFileReferenceSection(file); // PBXFileReference if (group) { if (this.getPBXGroupByKey(group)) { - this.removeFromPbxGroup(file, group); //Group other than Resources (i.e. 'splash') + this.removeFromPbxGroup(file, group); // Group other than Resources (i.e. 'splash') + } else if (this.getPBXVariantGroupByKey(group)) { + this.removeFromPbxVariantGroup(file, group); // PBXVariantGroup } - else if (this.getPBXVariantGroupByKey(group)) { - this.removeFromPbxVariantGroup(file, group); // PBXVariantGroup - } - } - else { - this.removeFromResourcesPbxGroup(file); // PBXGroup + } else { + this.removeFromResourcesPbxGroup(file); // PBXGroup } - this.removeFromPbxResourcesBuildPhase(file); // PBXResourcesBuildPhase + this.removeFromPbxResourcesBuildPhase(file); // PBXResourcesBuildPhase return file; -} +}; -pbxProject.prototype.addFramework = function(fpath, opt) { - var customFramework = opt && opt.customFramework == true; - var link = !opt || (opt.link == undefined || opt.link); //defaults to true if not specified - var embed = opt && opt.embed; //defaults to false if not specified +PBXProject.prototype.addFramework = function (fpath, opt) { + const customFramework = opt && opt.customFramework === true; + const link = !opt || (opt.link === undefined || opt.link); // defaults to true if not specified + const embed = opt && opt.embed; // defaults to false if not specified if (opt) { - delete opt.embed; + delete opt.embed; } - var file = new pbxFile(fpath, opt); + const file = new PBXFile(fpath, opt); file.uuid = this.generateUuid(); file.fileRef = this.generateUuid(); @@ -331,50 +382,48 @@ pbxProject.prototype.addFramework = function(fpath, opt) { if (this.hasFile(file.path)) return false; - this.addToPbxBuildFileSection(file); // PBXBuildFile - this.addToPbxFileReferenceSection(file); // PBXFileReference - this.addToFrameworksPbxGroup(file); // PBXGroup + this.addToPbxBuildFileSection(file); // PBXBuildFile + this.addToPbxFileReferenceSection(file); // PBXFileReference + this.addToFrameworksPbxGroup(file); // PBXGroup if (link) { - this.addToPbxFrameworksBuildPhase(file); // PBXFrameworksBuildPhase + this.addToPbxFrameworksBuildPhase(file); // PBXFrameworksBuildPhase } if (customFramework) { this.addToFrameworkSearchPaths(file); if (embed) { - opt.embed = embed; - var embeddedFile = new pbxFile(fpath, opt); + opt.embed = embed; + const embeddedFile = new PBXFile(fpath, opt); - embeddedFile.uuid = this.generateUuid(); - embeddedFile.fileRef = file.fileRef; + embeddedFile.uuid = this.generateUuid(); + embeddedFile.fileRef = file.fileRef; - //keeping a separate PBXBuildFile entry for Embed Frameworks - this.addToPbxBuildFileSection(embeddedFile); // PBXBuildFile + // keeping a separate PBXBuildFile entry for Embed Frameworks + this.addToPbxBuildFileSection(embeddedFile); // PBXBuildFile - this.addToPbxEmbedFrameworksBuildPhase(embeddedFile); // PBXCopyFilesBuildPhase + this.addToPbxEmbedFrameworksBuildPhase(embeddedFile); // PBXCopyFilesBuildPhase - return embeddedFile; + return embeddedFile; } } return file; -} - -pbxProject.prototype.removeFramework = function(fpath, opt) { - var embed = opt && opt.embed; +}; +PBXProject.prototype.removeFramework = function (fpath, opt) { if (opt) { - delete opt.embed; + delete opt.embed; } - var file = new pbxFile(fpath, opt); + const file = new PBXFile(fpath, opt); file.target = opt ? opt.target : undefined; - this.removeFromPbxBuildFileSection(file); // PBXBuildFile - this.removeFromPbxFileReferenceSection(file); // PBXFileReference - this.removeFromFrameworksPbxGroup(file); // PBXGroup - this.removeFromPbxFrameworksBuildPhase(file); // PBXFrameworksBuildPhase + this.removeFromPbxBuildFileSection(file); // PBXBuildFile + this.removeFromPbxFileReferenceSection(file); // PBXFileReference + this.removeFromFrameworksPbxGroup(file); // PBXGroup + this.removeFromPbxFrameworksBuildPhase(file); // PBXFrameworksBuildPhase if (opt && opt.customFramework) { this.removeFromFrameworkSearchPaths(file); @@ -382,19 +431,18 @@ pbxProject.prototype.removeFramework = function(fpath, opt) { opt = opt || {}; opt.embed = true; - var embeddedFile = new pbxFile(fpath, opt); + const embeddedFile = new PBXFile(fpath, opt); embeddedFile.fileRef = file.fileRef; - this.removeFromPbxBuildFileSection(embeddedFile); // PBXBuildFile + this.removeFromPbxBuildFileSection(embeddedFile); // PBXBuildFile this.removeFromPbxEmbedFrameworksBuildPhase(embeddedFile); // PBXCopyFilesBuildPhase return file; -} - +}; -pbxProject.prototype.addCopyfile = function(fpath, opt) { - var file = new pbxFile(fpath, opt); +PBXProject.prototype.addCopyfile = function (fpath, opt) { + let file = new PBXFile(fpath, opt); // catch duplicates if (this.hasFile(file.path)) { @@ -404,53 +452,53 @@ pbxProject.prototype.addCopyfile = function(fpath, opt) { file.fileRef = file.uuid = this.generateUuid(); file.target = opt ? opt.target : undefined; - this.addToPbxBuildFileSection(file); // PBXBuildFile - this.addToPbxFileReferenceSection(file); // PBXFileReference - this.addToPbxCopyfilesBuildPhase(file); // PBXCopyFilesBuildPhase + this.addToPbxBuildFileSection(file); // PBXBuildFile + this.addToPbxFileReferenceSection(file); // PBXFileReference + this.addToPbxCopyfilesBuildPhase(file); // PBXCopyFilesBuildPhase return file; -} +}; -pbxProject.prototype.pbxCopyfilesBuildPhaseObj = function(target) { +PBXProject.prototype.pbxCopyfilesBuildPhaseObj = function (target) { return this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Copy Files', target); -} +}; -pbxProject.prototype.addToPbxCopyfilesBuildPhase = function(file) { - var sources = this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Copy Files', file.target); +PBXProject.prototype.addToPbxCopyfilesBuildPhase = function (file) { + const sources = this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Copy Files', file.target); sources.files.push(pbxBuildPhaseObj(file)); -} +}; -pbxProject.prototype.removeCopyfile = function(fpath, opt) { - var file = new pbxFile(fpath, opt); +PBXProject.prototype.removeCopyfile = function (fpath, opt) { + const file = new PBXFile(fpath, opt); file.target = opt ? opt.target : undefined; - this.removeFromPbxBuildFileSection(file); // PBXBuildFile - this.removeFromPbxFileReferenceSection(file); // PBXFileReference - this.removeFromPbxCopyfilesBuildPhase(file); // PBXFrameworksBuildPhase + this.removeFromPbxBuildFileSection(file); // PBXBuildFile + this.removeFromPbxFileReferenceSection(file); // PBXFileReference + this.removeFromPbxCopyfilesBuildPhase(file); // PBXFrameworksBuildPhase return file; -} +}; -pbxProject.prototype.removeFromPbxCopyfilesBuildPhase = function(file) { - var sources = this.pbxCopyfilesBuildPhaseObj(file.target); - for (i in sources.files) { - if (sources.files[i].comment == longComment(file)) { +PBXProject.prototype.removeFromPbxCopyfilesBuildPhase = function (file) { + const sources = this.pbxCopyfilesBuildPhaseObj(file.target); + for (const i in sources.files) { + if (sources.files[i].comment === longComment(file)) { sources.files.splice(i, 1); break; } } -} +}; -pbxProject.prototype.addStaticLibrary = function(path, opt) { +PBXProject.prototype.addStaticLibrary = function (path, opt) { opt = opt || {}; - var file; + let file; if (opt.plugin) { file = this.addPluginFile(path, opt); if (!file) return false; } else { - file = new pbxFile(path, opt); + file = new PBXFile(path, opt); if (this.hasFile(file.path)) return false; } @@ -459,65 +507,65 @@ pbxProject.prototype.addStaticLibrary = function(path, opt) { if (!opt.plugin) { file.fileRef = this.generateUuid(); - this.addToPbxFileReferenceSection(file); // PBXFileReference + this.addToPbxFileReferenceSection(file); // PBXFileReference } - this.addToPbxBuildFileSection(file); // PBXBuildFile - this.addToPbxFrameworksBuildPhase(file); // PBXFrameworksBuildPhase - this.addToLibrarySearchPaths(file); // make sure it gets built! + this.addToPbxBuildFileSection(file); // PBXBuildFile + this.addToPbxFrameworksBuildPhase(file); // PBXFrameworksBuildPhase + this.addToLibrarySearchPaths(file); // make sure it gets built! return file; -} +}; // helper addition functions -pbxProject.prototype.addToPbxBuildFileSection = function(file) { - var commentKey = f("%s_comment", file.uuid); +PBXProject.prototype.addToPbxBuildFileSection = function (file) { + const commentKey = f('%s_comment', file.uuid); this.pbxBuildFileSection()[file.uuid] = pbxBuildFileObj(file); this.pbxBuildFileSection()[commentKey] = pbxBuildFileComment(file); -} +}; -pbxProject.prototype.removeFromPbxBuildFileSection = function(file) { - var uuid; +PBXProject.prototype.removeFromPbxBuildFileSection = function (file) { + let uuid; for (uuid in this.pbxBuildFileSection()) { - if (this.pbxBuildFileSection()[uuid].fileRef_comment == file.basename) { + if (this.pbxBuildFileSection()[uuid].fileRef_comment === file.basename) { file.uuid = uuid; delete this.pbxBuildFileSection()[uuid]; - var commentKey = f("%s_comment", uuid); + const commentKey = f('%s_comment', uuid); delete this.pbxBuildFileSection()[commentKey]; } } -} +}; -pbxProject.prototype.addPbxGroup = function(filePathsArray, name, path, sourceTree) { - var groups = this.hash.project.objects['PBXGroup'], - pbxGroupUuid = this.generateUuid(), - commentKey = f("%s_comment", pbxGroupUuid), - pbxGroup = { - isa: 'PBXGroup', - children: [], - name: name, - path: path, - sourceTree: sourceTree ? sourceTree : '""' - }, - fileReferenceSection = this.pbxFileReferenceSection(), - filePathToReference = {}; +PBXProject.prototype.addPbxGroup = function (filePathsArray, name, path, sourceTree) { + const groups = this.hash.project.objects.PBXGroup; + const pbxGroupUuid = this.generateUuid(); + const commentKey = f('%s_comment', pbxGroupUuid); + const pbxGroup = { + isa: 'PBXGroup', + children: [], + name, + path, + sourceTree: sourceTree || '""' + }; + const fileReferenceSection = this.pbxFileReferenceSection(); + const filePathToReference = {}; - for (var key in fileReferenceSection) { + for (const key in fileReferenceSection) { // only look for comments if (!COMMENT_KEY.test(key)) continue; - var fileReferenceKey = key.split(COMMENT_KEY)[0], - fileReference = fileReferenceSection[fileReferenceKey]; + const fileReferenceKey = key.split(COMMENT_KEY)[0]; + const fileReference = fileReferenceSection[fileReferenceKey]; filePathToReference[fileReference.path] = { fileRef: fileReferenceKey, basename: fileReferenceSection[key] }; } - for (var index = 0; index < filePathsArray.length; index++) { - var filePath = filePathsArray[index], - filePathQuoted = "\"" + filePath + "\""; + for (let index = 0; index < filePathsArray.length; index++) { + const filePath = filePathsArray[index]; + const filePathQuoted = '"' + filePath + '"'; if (filePathToReference[filePath]) { pbxGroup.children.push(pbxGroupChild(filePathToReference[filePath])); continue; @@ -526,11 +574,11 @@ pbxProject.prototype.addPbxGroup = function(filePathsArray, name, path, sourceTr continue; } - var file = new pbxFile(filePath); + const file = new PBXFile(filePath); file.uuid = this.generateUuid(); file.fileRef = this.generateUuid(); - this.addToPbxFileReferenceSection(file); // PBXFileReference - this.addToPbxBuildFileSection(file); // PBXBuildFile + this.addToPbxFileReferenceSection(file); // PBXFileReference + this.addToPbxBuildFileSection(file); // PBXBuildFile pbxGroup.children.push(pbxGroupChild(file)); } @@ -539,76 +587,73 @@ pbxProject.prototype.addPbxGroup = function(filePathsArray, name, path, sourceTr groups[commentKey] = name; } - return { uuid: pbxGroupUuid, pbxGroup: pbxGroup }; -} + return { uuid: pbxGroupUuid, pbxGroup }; +}; -pbxProject.prototype.removePbxGroup = function (groupName) { - var section = this.hash.project.objects['PBXGroup'], - key, itemKey; +PBXProject.prototype.removePbxGroup = function (groupName) { + const section = this.hash.project.objects.PBXGroup; + let itemKey; - for (key in section) { + for (const key in section) { // only look for comments if (!COMMENT_KEY.test(key)) continue; - if (section[key] == groupName) { + if (section[key] === groupName) { itemKey = key.split(COMMENT_KEY)[0]; delete section[itemKey]; } } -} - -pbxProject.prototype.addToPbxProjectSection = function(target) { +}; - var newTarget = { - value: target.uuid, - comment: pbxNativeTargetComment(target.pbxNativeTarget) - }; +PBXProject.prototype.addToPbxProjectSection = function (target) { + const newTarget = { + value: target.uuid, + comment: pbxNativeTargetComment(target.pbxNativeTarget) + }; - this.pbxProjectSection()[this.getFirstProject()['uuid']]['targets'].push(newTarget); -} + this.pbxProjectSection()[this.getFirstProject().uuid].targets.push(newTarget); +}; -pbxProject.prototype.addToPbxNativeTargetSection = function(target) { - var commentKey = f("%s_comment", target.uuid); +PBXProject.prototype.addToPbxNativeTargetSection = function (target) { + const commentKey = f('%s_comment', target.uuid); this.pbxNativeTargetSection()[target.uuid] = target.pbxNativeTarget; this.pbxNativeTargetSection()[commentKey] = target.pbxNativeTarget.name; -} +}; -pbxProject.prototype.addToPbxFileReferenceSection = function(file) { - var commentKey = f("%s_comment", file.fileRef); +PBXProject.prototype.addToPbxFileReferenceSection = function (file) { + const commentKey = f('%s_comment', file.fileRef); this.pbxFileReferenceSection()[file.fileRef] = pbxFileReferenceObj(file); this.pbxFileReferenceSection()[commentKey] = pbxFileReferenceComment(file); -} - -pbxProject.prototype.removeFromPbxFileReferenceSection = function(file) { +}; - var i; - var refObj = pbxFileReferenceObj(file); - for (i in this.pbxFileReferenceSection()) { - if (this.pbxFileReferenceSection()[i].name == refObj.name || - ('"' + this.pbxFileReferenceSection()[i].name + '"') == refObj.name || - this.pbxFileReferenceSection()[i].path == refObj.path || - ('"' + this.pbxFileReferenceSection()[i].path + '"') == refObj.path) { +PBXProject.prototype.removeFromPbxFileReferenceSection = function (file) { + const refObj = pbxFileReferenceObj(file); + for (const i in this.pbxFileReferenceSection()) { + if (this.pbxFileReferenceSection()[i].name === refObj.name || + ('"' + this.pbxFileReferenceSection()[i].name + '"') === refObj.name || + this.pbxFileReferenceSection()[i].path === refObj.path || + ('"' + this.pbxFileReferenceSection()[i].path + '"') === refObj.path) { file.fileRef = file.uuid = i; delete this.pbxFileReferenceSection()[i]; break; } } - var commentKey = f("%s_comment", file.fileRef); - if (this.pbxFileReferenceSection()[commentKey] != undefined) { + const commentKey = f('%s_comment', file.fileRef); + if (this.pbxFileReferenceSection()[commentKey] !== undefined) { delete this.pbxFileReferenceSection()[commentKey]; } return file; -} +}; -pbxProject.prototype.addToXcVersionGroupSection = function(file) { +PBXProject.prototype.addToXcVersionGroupSection = function (file) { if (!file.models || !file.currentModel) { - throw new Error("Cannot create a XCVersionGroup section from not a data model document file"); + throw new Error('Cannot create a XCVersionGroup section from not a data model document file'); } - var commentKey = f("%s_comment", file.fileRef); + const commentKey = f('%s_comment', file.fileRef); if (!this.xcVersionGroupSection()[file.fileRef]) { this.xcVersionGroupSection()[file.fileRef] = { @@ -622,184 +667,183 @@ pbxProject.prototype.addToXcVersionGroupSection = function(file) { }; this.xcVersionGroupSection()[commentKey] = path.basename(file.path); } -} +}; -pbxProject.prototype.addToPluginsPbxGroup = function(file) { - var pluginsGroup = this.pbxGroupByName('Plugins'); +PBXProject.prototype.addToPluginsPbxGroup = function (file) { + const pluginsGroup = this.pbxGroupByName('Plugins'); if (!pluginsGroup) { this.addPbxGroup([file.path], 'Plugins'); } else { pluginsGroup.children.push(pbxGroupChild(file)); } -} +}; -pbxProject.prototype.removeFromPluginsPbxGroup = function(file) { +PBXProject.prototype.removeFromPluginsPbxGroup = function (file) { if (!this.pbxGroupByName('Plugins')) { return null; } - var pluginsGroupChildren = this.pbxGroupByName('Plugins').children, i; - for (i in pluginsGroupChildren) { - if (pbxGroupChild(file).value == pluginsGroupChildren[i].value && - pbxGroupChild(file).comment == pluginsGroupChildren[i].comment) { + const pluginsGroupChildren = this.pbxGroupByName('Plugins').children; + for (const i in pluginsGroupChildren) { + if (pbxGroupChild(file).value === pluginsGroupChildren[i].value && + pbxGroupChild(file).comment === pluginsGroupChildren[i].comment) { pluginsGroupChildren.splice(i, 1); break; } } -} +}; -pbxProject.prototype.addToResourcesPbxGroup = function(file) { - var pluginsGroup = this.pbxGroupByName('Resources'); +PBXProject.prototype.addToResourcesPbxGroup = function (file) { + const pluginsGroup = this.pbxGroupByName('Resources'); if (!pluginsGroup) { this.addPbxGroup([file.path], 'Resources'); } else { pluginsGroup.children.push(pbxGroupChild(file)); } -} +}; -pbxProject.prototype.removeFromResourcesPbxGroup = function(file) { +PBXProject.prototype.removeFromResourcesPbxGroup = function (file) { if (!this.pbxGroupByName('Resources')) { return null; } - var pluginsGroupChildren = this.pbxGroupByName('Resources').children, i; - for (i in pluginsGroupChildren) { - if (pbxGroupChild(file).value == pluginsGroupChildren[i].value && - pbxGroupChild(file).comment == pluginsGroupChildren[i].comment) { + const pluginsGroupChildren = this.pbxGroupByName('Resources').children; + for (const i in pluginsGroupChildren) { + if (pbxGroupChild(file).value === pluginsGroupChildren[i].value && + pbxGroupChild(file).comment === pluginsGroupChildren[i].comment) { pluginsGroupChildren.splice(i, 1); break; } } -} +}; -pbxProject.prototype.addToFrameworksPbxGroup = function(file) { - var pluginsGroup = this.pbxGroupByName('Frameworks'); +PBXProject.prototype.addToFrameworksPbxGroup = function (file) { + const pluginsGroup = this.pbxGroupByName('Frameworks'); if (!pluginsGroup) { this.addPbxGroup([file.path], 'Frameworks'); } else { pluginsGroup.children.push(pbxGroupChild(file)); } -} +}; -pbxProject.prototype.removeFromFrameworksPbxGroup = function(file) { +PBXProject.prototype.removeFromFrameworksPbxGroup = function (file) { if (!this.pbxGroupByName('Frameworks')) { return null; } - var pluginsGroupChildren = this.pbxGroupByName('Frameworks').children; + const pluginsGroupChildren = this.pbxGroupByName('Frameworks').children; - for (i in pluginsGroupChildren) { - if (pbxGroupChild(file).value == pluginsGroupChildren[i].value && - pbxGroupChild(file).comment == pluginsGroupChildren[i].comment) { + for (const i in pluginsGroupChildren) { + if (pbxGroupChild(file).value === pluginsGroupChildren[i].value && + pbxGroupChild(file).comment === pluginsGroupChildren[i].comment) { pluginsGroupChildren.splice(i, 1); break; } } -} +}; -pbxProject.prototype.addToPbxEmbedFrameworksBuildPhase = function (file) { - var sources = this.pbxEmbedFrameworksBuildPhaseObj(file.target); +PBXProject.prototype.addToPbxEmbedFrameworksBuildPhase = function (file) { + const sources = this.pbxEmbedFrameworksBuildPhaseObj(file.target); if (sources) { sources.files.push(pbxBuildPhaseObj(file)); } -} +}; -pbxProject.prototype.removeFromPbxEmbedFrameworksBuildPhase = function (file) { - var sources = this.pbxEmbedFrameworksBuildPhaseObj(file.target); +PBXProject.prototype.removeFromPbxEmbedFrameworksBuildPhase = function (file) { + const sources = this.pbxEmbedFrameworksBuildPhaseObj(file.target); if (sources) { - var files = []; - for (i in sources.files) { - if (sources.files[i].comment != longComment(file)) { + const files = []; + for (const i in sources.files) { + if (sources.files[i].comment !== longComment(file)) { files.push(sources.files[i]); } } sources.files = files; } -} +}; -pbxProject.prototype.addToProductsPbxGroup = function(file) { - var productsGroup = this.pbxGroupByName('Products'); +PBXProject.prototype.addToProductsPbxGroup = function (file) { + const productsGroup = this.pbxGroupByName('Products'); if (!productsGroup) { this.addPbxGroup([file.path], 'Products'); } else { productsGroup.children.push(pbxGroupChild(file)); } -} +}; -pbxProject.prototype.removeFromProductsPbxGroup = function(file) { +PBXProject.prototype.removeFromProductsPbxGroup = function (file) { if (!this.pbxGroupByName('Products')) { return null; } - var productsGroupChildren = this.pbxGroupByName('Products').children, i; - for (i in productsGroupChildren) { - if (pbxGroupChild(file).value == productsGroupChildren[i].value && - pbxGroupChild(file).comment == productsGroupChildren[i].comment) { + const productsGroupChildren = this.pbxGroupByName('Products').children; + for (const i in productsGroupChildren) { + if (pbxGroupChild(file).value === productsGroupChildren[i].value && + pbxGroupChild(file).comment === productsGroupChildren[i].comment) { productsGroupChildren.splice(i, 1); break; } } -} +}; -pbxProject.prototype.addToPbxSourcesBuildPhase = function(file) { - var sources = this.pbxSourcesBuildPhaseObj(file.target); +PBXProject.prototype.addToPbxSourcesBuildPhase = function (file) { + const sources = this.pbxSourcesBuildPhaseObj(file.target); sources.files.push(pbxBuildPhaseObj(file)); -} - -pbxProject.prototype.removeFromPbxSourcesBuildPhase = function(file) { +}; - var sources = this.pbxSourcesBuildPhaseObj(file.target), i; - for (i in sources.files) { - if (sources.files[i].comment == longComment(file)) { +PBXProject.prototype.removeFromPbxSourcesBuildPhase = function (file) { + const sources = this.pbxSourcesBuildPhaseObj(file.target); + for (const i in sources.files) { + if (sources.files[i].comment === longComment(file)) { sources.files.splice(i, 1); break; } } -} +}; -pbxProject.prototype.addToPbxResourcesBuildPhase = function(file) { - var sources = this.pbxResourcesBuildPhaseObj(file.target); +PBXProject.prototype.addToPbxResourcesBuildPhase = function (file) { + const sources = this.pbxResourcesBuildPhaseObj(file.target); sources.files.push(pbxBuildPhaseObj(file)); -} +}; -pbxProject.prototype.removeFromPbxResourcesBuildPhase = function(file) { - var sources = this.pbxResourcesBuildPhaseObj(file.target), i; +PBXProject.prototype.removeFromPbxResourcesBuildPhase = function (file) { + const sources = this.pbxResourcesBuildPhaseObj(file.target); - for (i in sources.files) { - if (sources.files[i].comment == longComment(file)) { + for (const i in sources.files) { + if (sources.files[i].comment === longComment(file)) { sources.files.splice(i, 1); break; } } -} +}; -pbxProject.prototype.addToPbxFrameworksBuildPhase = function(file) { - var sources = this.pbxFrameworksBuildPhaseObj(file.target); +PBXProject.prototype.addToPbxFrameworksBuildPhase = function (file) { + const sources = this.pbxFrameworksBuildPhaseObj(file.target); sources.files.push(pbxBuildPhaseObj(file)); -} +}; -pbxProject.prototype.removeFromPbxFrameworksBuildPhase = function(file) { - var sources = this.pbxFrameworksBuildPhaseObj(file.target); - for (i in sources.files) { - if (sources.files[i].comment == longComment(file)) { +PBXProject.prototype.removeFromPbxFrameworksBuildPhase = function (file) { + const sources = this.pbxFrameworksBuildPhaseObj(file.target); + for (const i in sources.files) { + if (sources.files[i].comment === longComment(file)) { sources.files.splice(i, 1); break; } } -} +}; -pbxProject.prototype.addXCConfigurationList = function(configurationObjectsArray, defaultConfigurationName, comment) { - var pbxBuildConfigurationSection = this.pbxXCBuildConfigurationSection(), - pbxXCConfigurationListSection = this.pbxXCConfigurationList(), - xcConfigurationListUuid = this.generateUuid(), - commentKey = f("%s_comment", xcConfigurationListUuid), - xcConfigurationList = { - isa: 'XCConfigurationList', - buildConfigurations: [], - defaultConfigurationIsVisible: 0, - defaultConfigurationName: defaultConfigurationName - }; +PBXProject.prototype.addXCConfigurationList = function (configurationObjectsArray, defaultConfigurationName, comment) { + const pbxBuildConfigurationSection = this.pbxXCBuildConfigurationSection(); + const pbxXCConfigurationListSection = this.pbxXCConfigurationList(); + const xcConfigurationListUuid = this.generateUuid(); + const commentKey = f('%s_comment', xcConfigurationListUuid); + const xcConfigurationList = { + isa: 'XCConfigurationList', + buildConfigurations: [], + defaultConfigurationIsVisible: 0, + defaultConfigurationName + }; - for (var index = 0; index < configurationObjectsArray.length; index++) { - var configuration = configurationObjectsArray[index], - configurationUuid = this.generateUuid(), - configurationCommentKey = f("%s_comment", configurationUuid); + for (let index = 0; index < configurationObjectsArray.length; index++) { + const configuration = configurationObjectsArray[index]; + const configurationUuid = this.generateUuid(); + const configurationCommentKey = f('%s_comment', configurationUuid); pbxBuildConfigurationSection[configurationUuid] = configuration; pbxBuildConfigurationSection[configurationCommentKey] = configuration.name; @@ -811,87 +855,109 @@ pbxProject.prototype.addXCConfigurationList = function(configurationObjectsArray pbxXCConfigurationListSection[commentKey] = comment; } - return { uuid: xcConfigurationListUuid, xcConfigurationList: xcConfigurationList }; -} - -pbxProject.prototype.addTargetDependency = function(target, dependencyTargets) { - if (!target) - return undefined; - - var nativeTargets = this.pbxNativeTargetSection(); - - if (typeof nativeTargets[target] == "undefined") - throw new Error("Invalid target: " + target); - - for (var index = 0; index < dependencyTargets.length; index++) { - var dependencyTarget = dependencyTargets[index]; - if (typeof nativeTargets[dependencyTarget] == "undefined") - throw new Error("Invalid target: " + dependencyTarget); - } + return { uuid: xcConfigurationListUuid, xcConfigurationList }; +}; - var pbxTargetDependency = 'PBXTargetDependency', - pbxContainerItemProxy = 'PBXContainerItemProxy', - pbxTargetDependencySection = this.hash.project.objects[pbxTargetDependency], - pbxContainerItemProxySection = this.hash.project.objects[pbxContainerItemProxy]; - - for (var index = 0; index < dependencyTargets.length; index++) { - var dependencyTargetUuid = dependencyTargets[index], - dependencyTargetCommentKey = f("%s_comment", dependencyTargetUuid), - targetDependencyUuid = this.generateUuid(), - targetDependencyCommentKey = f("%s_comment", targetDependencyUuid), - itemProxyUuid = this.generateUuid(), - itemProxyCommentKey = f("%s_comment", itemProxyUuid), - itemProxy = { - isa: pbxContainerItemProxy, - containerPortal: this.hash.project['rootObject'], - containerPortal_comment: this.hash.project['rootObject_comment'], - proxyType: 1, - remoteGlobalIDString: dependencyTargetUuid, - remoteInfo: nativeTargets[dependencyTargetUuid].name - }, - targetDependency = { - isa: pbxTargetDependency, - target: dependencyTargetUuid, - target_comment: nativeTargets[dependencyTargetCommentKey], - targetProxy: itemProxyUuid, - targetProxy_comment: pbxContainerItemProxy - }; +PBXProject.prototype.addTargetDependency = function (target, dependencyTargets) { + if (!target) { return undefined; } + + const nativeTargets = this.pbxNativeTargetSection(); + + if (typeof nativeTargets[target] === 'undefined') { throw new Error('Invalid target: ' + target); } + + for (let index = 0; index < dependencyTargets.length; index++) { + const dependencyTarget = dependencyTargets[index]; + if (typeof nativeTargets[dependencyTarget] === 'undefined') { throw new Error('Invalid target: ' + dependencyTarget); } + } + + const pbxTargetDependency = 'PBXTargetDependency'; + const pbxContainerItemProxy = 'PBXContainerItemProxy'; + const pbxTargetDependencySection = this.hash.project.objects[pbxTargetDependency]; + const pbxContainerItemProxySection = this.hash.project.objects[pbxContainerItemProxy]; + + for (let index = 0; index < dependencyTargets.length; index++) { + const dependencyTargetUuid = dependencyTargets[index]; + const dependencyTargetCommentKey = f('%s_comment', dependencyTargetUuid); + const targetDependencyUuid = this.generateUuid(); + const targetDependencyCommentKey = f('%s_comment', targetDependencyUuid); + const itemProxyUuid = this.generateUuid(); + const itemProxyCommentKey = f('%s_comment', itemProxyUuid); + const itemProxy = { + isa: pbxContainerItemProxy, + containerPortal: this.hash.project.rootObject, + containerPortal_comment: this.hash.project.rootObject_comment, + proxyType: 1, + remoteGlobalIDString: dependencyTargetUuid, + remoteInfo: nativeTargets[dependencyTargetUuid].name + }; + const targetDependency = { + isa: pbxTargetDependency, + target: dependencyTargetUuid, + target_comment: nativeTargets[dependencyTargetCommentKey], + targetProxy: itemProxyUuid, + targetProxy_comment: pbxContainerItemProxy + }; if (pbxContainerItemProxySection && pbxTargetDependencySection) { pbxContainerItemProxySection[itemProxyUuid] = itemProxy; pbxContainerItemProxySection[itemProxyCommentKey] = pbxContainerItemProxy; pbxTargetDependencySection[targetDependencyUuid] = targetDependency; pbxTargetDependencySection[targetDependencyCommentKey] = pbxTargetDependency; - nativeTargets[target].dependencies.push({ value: targetDependencyUuid, comment: pbxTargetDependency }) + nativeTargets[target].dependencies.push({ value: targetDependencyUuid, comment: pbxTargetDependency }); } } return { uuid: target, target: nativeTargets[target] }; -} +}; -pbxProject.prototype.addBuildPhase = function(filePathsArray, buildPhaseType, comment, target, optionsOrFolderType, subfolderPath) { - var buildPhaseSection, - fileReferenceSection = this.pbxFileReferenceSection(), - buildFileSection = this.pbxBuildFileSection(), - buildPhaseUuid = this.generateUuid(), - buildPhaseTargetUuid = target || this.getFirstTarget().uuid, - commentKey = f("%s_comment", buildPhaseUuid), - buildPhase = { - isa: buildPhaseType, - buildActionMask: 2147483647, - files: [], - runOnlyForDeploymentPostprocessing: 0 - }, - filePathToBuildFile = {}; +/** + * Add files to specific build phase by defining the build phase type. + * + * @example + * // Adding a file to Resource Build Phase. + * myProject.addBuildPhase( + * ['MyAssets.xcassets'], + * 'PBXResourcesBuildPhase', + * 'Resources' + * ); + * + * @param {string[]} filePathsArray collection of file paths + * @param {BuildPhaseType} buildPhaseType target build phase + * @param {string} comment name of the build phase. (e.g. "Copy My Files") + * @param {string} target UUID of the PBXNativeTarget (defaults to first target) + * @param {CopyFilesTargetType|ShellScriptOptions} optionsOrFolderType either sell script options or copy files target type + * @param {string} subfolderPath copy files subfolder path (default: "") + * @returns {AddBuildPhaseResults} object containing the build phase & uuid + */ +PBXProject.prototype.addBuildPhase = function (filePathsArray, buildPhaseType, comment, target, optionsOrFolderType, subfolderPath) { + // Xcode may introduce new build phase types so the buildPhaseType + // param will not be validated against a fixed set of values. + // Instead, it will reject object keys that shouldn't be writable. + if (RESTRICTED_OBJECT_KEYS.has(buildPhaseType)) { + throw new Error(`"${buildPhaseType}" is restricted and cannot be used as a build phase type.`); + } + + const fileReferenceSection = this.pbxFileReferenceSection(); + const buildFileSection = this.pbxBuildFileSection(); + const buildPhaseUuid = this.generateUuid(); + const buildPhaseTargetUuid = target || this.getFirstTarget().uuid; + const commentKey = f('%s_comment', buildPhaseUuid); + let buildPhase = { + isa: buildPhaseType, + buildActionMask: 2147483647, + files: [], + runOnlyForDeploymentPostprocessing: 0 + }; + const filePathToBuildFile = {}; if (buildPhaseType === 'PBXCopyFilesBuildPhase') { buildPhase = pbxCopyFilesBuildPhaseObj(buildPhase, optionsOrFolderType, subfolderPath, comment); } else if (buildPhaseType === 'PBXShellScriptBuildPhase') { - buildPhase = pbxShellScriptBuildPhaseObj(buildPhase, optionsOrFolderType, comment) + buildPhase = pbxShellScriptBuildPhaseObj(buildPhase, optionsOrFolderType, comment); } if (!this.hash.project.objects[buildPhaseType]) { - this.hash.project.objects[buildPhaseType] = new Object(); + this.hash.project.objects[buildPhaseType] = {}; } if (!this.hash.project.objects[buildPhaseType][buildPhaseUuid]) { @@ -899,35 +965,48 @@ pbxProject.prototype.addBuildPhase = function(filePathsArray, buildPhaseType, co this.hash.project.objects[buildPhaseType][commentKey] = comment; } - if (this.hash.project.objects['PBXNativeTarget'][buildPhaseTargetUuid]['buildPhases']) { - this.hash.project.objects['PBXNativeTarget'][buildPhaseTargetUuid]['buildPhases'].push({ + if (this.hash.project.objects.PBXNativeTarget[buildPhaseTargetUuid].buildPhases) { + this.hash.project.objects.PBXNativeTarget[buildPhaseTargetUuid].buildPhases.push({ value: buildPhaseUuid, - comment: comment - }) - + comment + }); } - - for (var key in buildFileSection) { + for (const key in buildFileSection) { // only look for comments if (!COMMENT_KEY.test(key)) continue; - var buildFileKey = key.split(COMMENT_KEY)[0], - buildFile = buildFileSection[buildFileKey]; - fileReference = fileReferenceSection[buildFile.fileRef]; + const buildFileKey = key.split(COMMENT_KEY)[0]; + const buildFile = buildFileSection[buildFileKey]; + const fileReference = fileReferenceSection[buildFile.fileRef]; - if (!fileReference) continue; + // If a file reference does not define either the name or path property, + // it will not be included to the filePathToBuildFile lookup table. + // If the file reference defines both properies, the path property will + // take priority. + const fileIdentifier = fileReference?.path || fileReference?.name; - var pbxFileObj = new pbxFile(fileReference.path); + if (!fileIdentifier) { + continue; + } + + const pbxFileObj = new PBXFile(fileIdentifier); - filePathToBuildFile[fileReference.path] = { uuid: buildFileKey, basename: pbxFileObj.basename, group: pbxFileObj.group }; + // Creates a lookup table of existing PBXBuildFile entries keyed by fileIdentifier. + // Used later when adding files to the build phase to reuse the existing PBXBuildFile + // instead of generating new PBXBuildFile. + filePathToBuildFile[fileIdentifier] = { + uuid: buildFileKey, + basename: pbxFileObj.basename, + group: pbxFileObj.group + }; } - for (var index = 0; index < filePathsArray.length; index++) { - var filePath = filePathsArray[index], - filePathQuoted = "\"" + filePath + "\"", - file = new pbxFile(filePath); + for (let index = 0; index < filePathsArray.length; index++) { + const filePath = filePathsArray[index]; + const filePathQuoted = '"' + filePath + '"'; + // Checks for an existing PBXBuildFile entry from the filePathToBuildFile lookup table. if (filePathToBuildFile[filePath]) { buildPhase.files.push(pbxBuildPhaseObj(filePathToBuildFile[filePath])); continue; @@ -936,417 +1015,438 @@ pbxProject.prototype.addBuildPhase = function(filePathsArray, buildPhaseType, co continue; } + // If no PBXBuildFile entry is found in the lookup table, a new entry is created + // with a new UUID. It is then: + // 1. Added to the PBXFileReferenceSection + // 2. Added to the PBXBuildFileSection + // 3. Pushed onto the build phase file list. + const file = new PBXFile(filePath); file.uuid = this.generateUuid(); file.fileRef = this.generateUuid(); - this.addToPbxFileReferenceSection(file); // PBXFileReference - this.addToPbxBuildFileSection(file); // PBXBuildFile + this.addToPbxFileReferenceSection(file); + this.addToPbxBuildFileSection(file); buildPhase.files.push(pbxBuildPhaseObj(file)); } - if (buildPhaseSection) { - buildPhaseSection[buildPhaseUuid] = buildPhase; - buildPhaseSection[commentKey] = comment; - } - - return { uuid: buildPhaseUuid, buildPhase: buildPhase }; -} + return { uuid: buildPhaseUuid, buildPhase }; +}; // helper access functions -pbxProject.prototype.pbxProjectSection = function() { - return this.hash.project.objects['PBXProject']; -} -pbxProject.prototype.pbxBuildFileSection = function() { - return this.hash.project.objects['PBXBuildFile']; -} +PBXProject.prototype.pbxProjectSection = function () { + return this.hash.project.objects.PBXProject; +}; +PBXProject.prototype.pbxBuildFileSection = function () { + return this.hash.project.objects.PBXBuildFile; +}; -pbxProject.prototype.pbxXCBuildConfigurationSection = function() { - return this.hash.project.objects['XCBuildConfiguration']; -} +PBXProject.prototype.pbxXCBuildConfigurationSection = function () { + return this.hash.project.objects.XCBuildConfiguration; +}; -pbxProject.prototype.pbxFileReferenceSection = function() { - return this.hash.project.objects['PBXFileReference']; -} +PBXProject.prototype.pbxFileReferenceSection = function () { + return this.hash.project.objects.PBXFileReference; +}; -pbxProject.prototype.pbxNativeTargetSection = function() { - return this.hash.project.objects['PBXNativeTarget']; -} +PBXProject.prototype.pbxNativeTargetSection = function () { + return this.hash.project.objects.PBXNativeTarget; +}; -pbxProject.prototype.xcVersionGroupSection = function () { - if (typeof this.hash.project.objects['XCVersionGroup'] !== 'object') { - this.hash.project.objects['XCVersionGroup'] = {}; +PBXProject.prototype.xcVersionGroupSection = function () { + if (typeof this.hash.project.objects.XCVersionGroup !== 'object') { + this.hash.project.objects.XCVersionGroup = {}; } - return this.hash.project.objects['XCVersionGroup']; -} + return this.hash.project.objects.XCVersionGroup; +}; -pbxProject.prototype.pbxXCConfigurationList = function() { - return this.hash.project.objects['XCConfigurationList']; -} +PBXProject.prototype.pbxXCConfigurationList = function () { + return this.hash.project.objects.XCConfigurationList; +}; -pbxProject.prototype.pbxGroupByName = function(name) { - var groups = this.hash.project.objects['PBXGroup'], - key, groupKey; +PBXProject.prototype.pbxGroupByName = function (name) { + const groups = this.hash.project.objects.PBXGroup; + let groupKey; - for (key in groups) { + for (const key in groups) { // only look for comments if (!COMMENT_KEY.test(key)) continue; - if (groups[key] == name) { + if (groups[key] === name) { groupKey = key.split(COMMENT_KEY)[0]; return groups[groupKey]; } } return null; -} +}; -pbxProject.prototype.pbxTargetByName = function(name) { +PBXProject.prototype.pbxTargetByName = function (name) { return this.pbxItemByComment(name, 'PBXNativeTarget'); -} +}; -pbxProject.prototype.findTargetKey = function(name) { - var targets = this.hash.project.objects['PBXNativeTarget']; +PBXProject.prototype.findTargetKey = function (name) { + const targets = this.hash.project.objects.PBXNativeTarget; - for (var key in targets) { + for (const key in targets) { // only look for comments if (COMMENT_KEY.test(key)) continue; - var target = targets[key]; + const target = targets[key]; if (target.name === name) { return key; } } return null; -} +}; -pbxProject.prototype.pbxItemByComment = function(name, pbxSectionName) { - var section = this.hash.project.objects[pbxSectionName], - key, itemKey; +PBXProject.prototype.pbxItemByComment = function (name, pbxSectionName) { + const section = this.hash.project.objects[pbxSectionName]; + let itemKey; - for (key in section) { + for (const key in section) { // only look for comments if (!COMMENT_KEY.test(key)) continue; - if (section[key] == name) { + if (section[key] === name) { itemKey = key.split(COMMENT_KEY)[0]; return section[itemKey]; } } return null; -} +}; -pbxProject.prototype.pbxSourcesBuildPhaseObj = function(target) { +PBXProject.prototype.pbxSourcesBuildPhaseObj = function (target) { return this.buildPhaseObject('PBXSourcesBuildPhase', 'Sources', target); -} +}; -pbxProject.prototype.pbxResourcesBuildPhaseObj = function(target) { +PBXProject.prototype.pbxResourcesBuildPhaseObj = function (target) { return this.buildPhaseObject('PBXResourcesBuildPhase', 'Resources', target); -} +}; -pbxProject.prototype.pbxFrameworksBuildPhaseObj = function(target) { +PBXProject.prototype.pbxFrameworksBuildPhaseObj = function (target) { return this.buildPhaseObject('PBXFrameworksBuildPhase', 'Frameworks', target); -} +}; -pbxProject.prototype.pbxEmbedFrameworksBuildPhaseObj = function (target) { +PBXProject.prototype.pbxEmbedFrameworksBuildPhaseObj = function (target) { return this.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Frameworks', target); }; // Find Build Phase from group/target -pbxProject.prototype.buildPhase = function(group, target) { - - if (!target) - return undefined; - - var nativeTargets = this.pbxNativeTargetSection(); - if (typeof nativeTargets[target] == "undefined") - throw new Error("Invalid target: " + target); - - var nativeTarget = nativeTargets[target]; - var buildPhases = nativeTarget.buildPhases; - for(var i in buildPhases) - { - var buildPhase = buildPhases[i]; - if (buildPhase.comment==group) - return buildPhase.value + "_comment"; - } - } +PBXProject.prototype.buildPhase = function (group, target) { + if (!target) { return undefined; } + + const nativeTargets = this.pbxNativeTargetSection(); + if (typeof nativeTargets[target] === 'undefined') { throw new Error('Invalid target: ' + target); } -pbxProject.prototype.buildPhaseObject = function(name, group, target) { - var section = this.hash.project.objects[name], - obj, sectionKey, key; - var buildPhase = this.buildPhase(group, target); + const nativeTarget = nativeTargets[target]; + const buildPhases = nativeTarget.buildPhases; + for (const i in buildPhases) { + const buildPhase = buildPhases[i]; + if (buildPhase.comment === group) { return buildPhase.value + '_comment'; } + } +}; - for (key in section) { +PBXProject.prototype.buildPhaseObject = function (name, group, target) { + const section = this.hash.project.objects[name]; + let sectionKey; + const buildPhase = this.buildPhase(group, target); + for (const key in section) { // only look for comments if (!COMMENT_KEY.test(key)) continue; // select the proper buildPhase - if (buildPhase && buildPhase!=key) - continue; - if (section[key] == group) { + if (buildPhase && buildPhase !== key) { continue; } + if (section[key] === group) { sectionKey = key.split(COMMENT_KEY)[0]; return section[sectionKey]; } } return null; -} +}; -pbxProject.prototype.addBuildProperty = function(prop, value, build_name) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - key, configuration; +PBXProject.prototype.addBuildProperty = function (prop, value, build_name) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + let configuration; - for (key in configurations){ + for (const key in configurations) { configuration = configurations[key]; - if (!build_name || configuration.name === build_name){ + if (!build_name || configuration.name === build_name) { configuration.buildSettings[prop] = value; } } -} +}; -pbxProject.prototype.removeBuildProperty = function(prop, build_name) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - key, configuration; +PBXProject.prototype.removeBuildProperty = function (prop, build_name) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + let configuration; - for (key in configurations){ + for (const key in configurations) { configuration = configurations[key]; - if (configuration.buildSettings[prop] && - !build_name || configuration.name === build_name){ + if ( + configuration.buildSettings[prop] && + (!build_name || configuration.name === build_name) + ) { delete configuration.buildSettings[prop]; } } -} +}; /** * * @param prop {String} * @param value {String|Array|Object|Number|Boolean} * @param build {String} Release or Debug + * @param targetName {String} the target which will be updated */ -pbxProject.prototype.updateBuildProperty = function(prop, value, build) { - var configs = this.pbxXCBuildConfigurationSection(); - for (var configName in configs) { +PBXProject.prototype.updateBuildProperty = function (prop, value, build, targetName) { + const validConfigs = []; + + if (targetName) { + const target = this.pbxTargetByName(targetName); + const targetBuildConfigs = target && target.buildConfigurationList; + + const xcConfigList = this.pbxXCConfigurationList(); + + // Collect the UUID's from the configuration of our target + for (const configName in xcConfigList) { + if (!COMMENT_KEY.test(configName) && targetBuildConfigs === configName) { + const buildVariants = xcConfigList[configName].buildConfigurations; + + for (const item of buildVariants) { + validConfigs.push(item.value); + } + + break; + } + } + } + + const configs = this.pbxXCBuildConfigurationSection(); + for (const configName in configs) { if (!COMMENT_KEY.test(configName)) { - var config = configs[configName]; - if ( (build && config.name === build) || (!build) ) { + if (targetName && !validConfigs.includes(configName)) continue; + + const config = configs[configName]; + if ((build && config.name === build) || (!build)) { config.buildSettings[prop] = value; } } } -} +}; -pbxProject.prototype.updateProductName = function(name) { +PBXProject.prototype.updateProductName = function (name) { this.updateBuildProperty('PRODUCT_NAME', '"' + name + '"'); -} +}; -pbxProject.prototype.removeFromFrameworkSearchPaths = function(file) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - INHERITED = '"$(inherited)"', - SEARCH_PATHS = 'FRAMEWORK_SEARCH_PATHS', - config, buildSettings, searchPaths; - var new_path = searchPathForFile(file, this); +PBXProject.prototype.removeFromFrameworkSearchPaths = function (file) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + const SEARCH_PATHS = 'FRAMEWORK_SEARCH_PATHS'; + let config; + let buildSettings; + let searchPaths; + const new_path = searchPathForFile(file, this); for (config in configurations) { buildSettings = configurations[config].buildSettings; - if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) - continue; + if (unquote(buildSettings.PRODUCT_NAME) !== this.productName) { continue; } searchPaths = buildSettings[SEARCH_PATHS]; if (searchPaths && Array.isArray(searchPaths)) { - var matches = searchPaths.filter(function(p) { + const matches = searchPaths.filter(function (p) { return p.indexOf(new_path) > -1; }); - matches.forEach(function(m) { - var idx = searchPaths.indexOf(m); + matches.forEach(function (m) { + const idx = searchPaths.indexOf(m); searchPaths.splice(idx, 1); }); } } -} +}; -pbxProject.prototype.addToFrameworkSearchPaths = function(file) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - INHERITED = '"$(inherited)"', - config, buildSettings, searchPaths; +PBXProject.prototype.addToFrameworkSearchPaths = function (file) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + const INHERITED = '"$(inherited)"'; + let config; + let buildSettings; for (config in configurations) { buildSettings = configurations[config].buildSettings; - if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) - continue; + if (unquote(buildSettings.PRODUCT_NAME) !== this.productName) { continue; } - if (!buildSettings['FRAMEWORK_SEARCH_PATHS'] - || buildSettings['FRAMEWORK_SEARCH_PATHS'] === INHERITED) { - buildSettings['FRAMEWORK_SEARCH_PATHS'] = [INHERITED]; + if (!buildSettings.FRAMEWORK_SEARCH_PATHS || + buildSettings.FRAMEWORK_SEARCH_PATHS === INHERITED) { + buildSettings.FRAMEWORK_SEARCH_PATHS = [INHERITED]; } - buildSettings['FRAMEWORK_SEARCH_PATHS'].push(searchPathForFile(file, this)); + buildSettings.FRAMEWORK_SEARCH_PATHS.push(searchPathForFile(file, this)); } -} +}; -pbxProject.prototype.removeFromLibrarySearchPaths = function(file) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - INHERITED = '"$(inherited)"', - SEARCH_PATHS = 'LIBRARY_SEARCH_PATHS', - config, buildSettings, searchPaths; - var new_path = searchPathForFile(file, this); +PBXProject.prototype.removeFromLibrarySearchPaths = function (file) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + const SEARCH_PATHS = 'LIBRARY_SEARCH_PATHS'; + let config; + let buildSettings; + let searchPaths; + const new_path = searchPathForFile(file, this); for (config in configurations) { buildSettings = configurations[config].buildSettings; - if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) - continue; + if (unquote(buildSettings.PRODUCT_NAME) !== this.productName) { continue; } searchPaths = buildSettings[SEARCH_PATHS]; if (searchPaths && Array.isArray(searchPaths)) { - var matches = searchPaths.filter(function(p) { + const matches = searchPaths.filter(function (p) { return p.indexOf(new_path) > -1; }); - matches.forEach(function(m) { - var idx = searchPaths.indexOf(m); + matches.forEach(function (m) { + const idx = searchPaths.indexOf(m); searchPaths.splice(idx, 1); }); } - } -} +}; -pbxProject.prototype.addToLibrarySearchPaths = function(file) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - INHERITED = '"$(inherited)"', - config, buildSettings, searchPaths; +PBXProject.prototype.addToLibrarySearchPaths = function (file) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + const INHERITED = '"$(inherited)"'; + let config; + let buildSettings; for (config in configurations) { buildSettings = configurations[config].buildSettings; - if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) - continue; + if (unquote(buildSettings.PRODUCT_NAME) !== this.productName) { continue; } - if (!buildSettings['LIBRARY_SEARCH_PATHS'] - || buildSettings['LIBRARY_SEARCH_PATHS'] === INHERITED) { - buildSettings['LIBRARY_SEARCH_PATHS'] = [INHERITED]; + if (!buildSettings.LIBRARY_SEARCH_PATHS || + buildSettings.LIBRARY_SEARCH_PATHS === INHERITED) { + buildSettings.LIBRARY_SEARCH_PATHS = [INHERITED]; } if (typeof file === 'string') { - buildSettings['LIBRARY_SEARCH_PATHS'].push(file); + buildSettings.LIBRARY_SEARCH_PATHS.push(file); } else { - buildSettings['LIBRARY_SEARCH_PATHS'].push(searchPathForFile(file, this)); + buildSettings.LIBRARY_SEARCH_PATHS.push(searchPathForFile(file, this)); } } -} +}; -pbxProject.prototype.removeFromHeaderSearchPaths = function(file) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - INHERITED = '"$(inherited)"', - SEARCH_PATHS = 'HEADER_SEARCH_PATHS', - config, buildSettings, searchPaths; - var new_path = searchPathForFile(file, this); +PBXProject.prototype.removeFromHeaderSearchPaths = function (file) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + const SEARCH_PATHS = 'HEADER_SEARCH_PATHS'; + let config; + let buildSettings; + const new_path = searchPathForFile(file, this); for (config in configurations) { buildSettings = configurations[config].buildSettings; - if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) - continue; + if (unquote(buildSettings.PRODUCT_NAME) !== this.productName) { continue; } if (buildSettings[SEARCH_PATHS]) { - var matches = buildSettings[SEARCH_PATHS].filter(function(p) { + const matches = buildSettings[SEARCH_PATHS].filter(function (p) { return p.indexOf(new_path) > -1; }); - matches.forEach(function(m) { - var idx = buildSettings[SEARCH_PATHS].indexOf(m); + matches.forEach(function (m) { + const idx = buildSettings[SEARCH_PATHS].indexOf(m); buildSettings[SEARCH_PATHS].splice(idx, 1); }); } - } -} -pbxProject.prototype.addToHeaderSearchPaths = function(file) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - INHERITED = '"$(inherited)"', - config, buildSettings, searchPaths; +}; +PBXProject.prototype.addToHeaderSearchPaths = function (file) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + const INHERITED = '"$(inherited)"'; + let config; + let buildSettings; for (config in configurations) { buildSettings = configurations[config].buildSettings; - if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) - continue; + if (unquote(buildSettings.PRODUCT_NAME) !== this.productName) { continue; } - if (!buildSettings['HEADER_SEARCH_PATHS']) { - buildSettings['HEADER_SEARCH_PATHS'] = [INHERITED]; + if (!buildSettings.HEADER_SEARCH_PATHS) { + buildSettings.HEADER_SEARCH_PATHS = [INHERITED]; } if (typeof file === 'string') { - buildSettings['HEADER_SEARCH_PATHS'].push(file); + buildSettings.HEADER_SEARCH_PATHS.push(file); } else { - buildSettings['HEADER_SEARCH_PATHS'].push(searchPathForFile(file, this)); + buildSettings.HEADER_SEARCH_PATHS.push(searchPathForFile(file, this)); } } -} +}; -pbxProject.prototype.addToOtherLinkerFlags = function (flag) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - INHERITED = '"$(inherited)"', - OTHER_LDFLAGS = 'OTHER_LDFLAGS', - config, buildSettings; +PBXProject.prototype.addToOtherLinkerFlags = function (flag) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + const INHERITED = '"$(inherited)"'; + const OTHER_LDFLAGS = 'OTHER_LDFLAGS'; + let config; + let buildSettings; for (config in configurations) { buildSettings = configurations[config].buildSettings; - if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) - continue; + if (unquote(buildSettings.PRODUCT_NAME) !== this.productName) { continue; } - if (!buildSettings[OTHER_LDFLAGS] - || buildSettings[OTHER_LDFLAGS] === INHERITED) { + if (!buildSettings[OTHER_LDFLAGS] || + buildSettings[OTHER_LDFLAGS] === INHERITED) { buildSettings[OTHER_LDFLAGS] = [INHERITED]; } buildSettings[OTHER_LDFLAGS].push(flag); } -} +}; -pbxProject.prototype.removeFromOtherLinkerFlags = function (flag) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - OTHER_LDFLAGS = 'OTHER_LDFLAGS', - config, buildSettings; +PBXProject.prototype.removeFromOtherLinkerFlags = function (flag) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + const OTHER_LDFLAGS = 'OTHER_LDFLAGS'; + let config; + let buildSettings; for (config in configurations) { buildSettings = configurations[config].buildSettings; - if (unquote(buildSettings['PRODUCT_NAME']) != this.productName) { + if (unquote(buildSettings.PRODUCT_NAME) !== this.productName) { continue; } if (buildSettings[OTHER_LDFLAGS]) { - var matches = buildSettings[OTHER_LDFLAGS].filter(function (p) { + const matches = buildSettings[OTHER_LDFLAGS].filter(function (p) { return p.indexOf(flag) > -1; }); matches.forEach(function (m) { - var idx = buildSettings[OTHER_LDFLAGS].indexOf(m); + const idx = buildSettings[OTHER_LDFLAGS].indexOf(m); buildSettings[OTHER_LDFLAGS].splice(idx, 1); }); } } -} +}; -pbxProject.prototype.addToBuildSettings = function (buildSetting, value) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - config, buildSettings; +PBXProject.prototype.addToBuildSettings = function (buildSetting, value) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + let config; + let buildSettings; for (config in configurations) { buildSettings = configurations[config].buildSettings; buildSettings[buildSetting] = value; } -} +}; -pbxProject.prototype.removeFromBuildSettings = function (buildSetting) { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - config, buildSettings; +PBXProject.prototype.removeFromBuildSettings = function (buildSetting) { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + let config; + let buildSettings; for (config in configurations) { buildSettings = configurations[config].buildSettings; @@ -1355,15 +1455,16 @@ pbxProject.prototype.removeFromBuildSettings = function (buildSetting) { delete buildSettings[buildSetting]; } } -} +}; // a JS getter. hmmm -pbxProject.prototype.__defineGetter__("productName", function() { - var configurations = nonComments(this.pbxXCBuildConfigurationSection()), - config, productName; +PBXProject.prototype.__defineGetter__('productName', function () { + const configurations = nonComments(this.pbxXCBuildConfigurationSection()); + let config; + let productName; for (config in configurations) { - productName = configurations[config].buildSettings['PRODUCT_NAME']; + productName = configurations[config].buildSettings.PRODUCT_NAME; if (productName) { return unquote(productName); @@ -1372,50 +1473,52 @@ pbxProject.prototype.__defineGetter__("productName", function() { }); // check if file is present -pbxProject.prototype.hasFile = function(filePath) { - var files = nonComments(this.pbxFileReferenceSection()), - file, id; +PBXProject.prototype.hasFile = function (filePath) { + const files = nonComments(this.pbxFileReferenceSection()); + let file; + let id; + for (id in files) { file = files[id]; - if (file.path == filePath || file.path == ('"' + filePath + '"')) { + if (file.path === filePath || file.path === ('"' + filePath + '"')) { return file; } } return false; -} - -pbxProject.prototype.addTarget = function(name, type, subfolder) { +}; +PBXProject.prototype.addTarget = function (name, type, subfolder, bundleId) { // Setup uuid and name of new target - var targetUuid = this.generateUuid(), - targetType = type, - targetSubfolder = subfolder || name, - targetName = name.trim(); + const targetUuid = this.generateUuid(); + const targetType = type; + const targetSubfolder = (subfolder || name).replace(/\\/g, '/'); + const targetName = name.trim(); + const targetBundleId = bundleId; // Check type against list of allowed target types if (!targetName) { - throw new Error("Target name missing."); + throw new Error('Target name missing.'); } // Check type against list of allowed target types if (!targetType) { - throw new Error("Target type missing."); + throw new Error('Target type missing.'); } // Check type against list of allowed target types if (!producttypeForTargettype(targetType)) { - throw new Error("Target type invalid: " + targetType); + throw new Error('Target type invalid: ' + targetType); } // Build Configuration: Create - var buildConfigurationsList = [ + let buildConfigurationsList = [ { name: 'Debug', isa: 'XCBuildConfiguration', buildSettings: { GCC_PREPROCESSOR_DEFINITIONS: ['"DEBUG=1"', '"$(inherited)"'], - INFOPLIST_FILE: '"' + path.join(targetSubfolder, targetSubfolder + '-Info.plist' + '"'), + INFOPLIST_FILE: '"' + path.posix.join(targetSubfolder, targetSubfolder + '-Info.plist' + '"'), LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"', PRODUCT_NAME: '"' + targetName + '"', SKIP_INSTALL: 'YES' @@ -1425,7 +1528,7 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) { name: 'Release', isa: 'XCBuildConfiguration', buildSettings: { - INFOPLIST_FILE: '"' + path.join(targetSubfolder, targetSubfolder + '-Info.plist' + '"'), + INFOPLIST_FILE: '"' + path.posix.join(targetSubfolder, targetSubfolder + '-Info.plist' + '"'), LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"', PRODUCT_NAME: '"' + targetName + '"', SKIP_INSTALL: 'YES' @@ -1433,49 +1536,54 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) { } ]; + // Add optional bundleId to build configuration + if (targetBundleId) { + buildConfigurationsList = buildConfigurationsList.map((elem) => { + elem.buildSettings.PRODUCT_BUNDLE_IDENTIFIER = '"' + targetBundleId + '"'; + return elem; + }); + } + // Build Configuration: Add - var buildConfigurations = this.addXCConfigurationList(buildConfigurationsList, 'Release', 'Build configuration list for PBXNativeTarget "' + targetName +'"'); + const buildConfigurations = this.addXCConfigurationList(buildConfigurationsList, 'Release', 'Build configuration list for PBXNativeTarget "' + targetName + '"'); // Product: Create - var productName = targetName, - productType = producttypeForTargettype(targetType), - productFileType = filetypeForProducttype(productType), - productFile = this.addProductFile(productName, { group: 'Copy Files', 'target': targetUuid, 'explicitFileType': productFileType}), - productFileName = productFile.basename; - + const productName = targetName; + const productType = producttypeForTargettype(targetType); + const productFileType = filetypeForProducttype(productType); + const productFile = this.addProductFile(productName, { group: 'Copy Files', target: targetUuid, explicitFileType: productFileType }); // Product: Add to build file list this.addToPbxBuildFileSection(productFile); // Target: Create - var target = { - uuid: targetUuid, - pbxNativeTarget: { - isa: 'PBXNativeTarget', - name: '"' + targetName + '"', - productName: '"' + targetName + '"', - productReference: productFile.fileRef, - productType: '"' + producttypeForTargettype(targetType) + '"', - buildConfigurationList: buildConfigurations.uuid, - buildPhases: [], - buildRules: [], - dependencies: [] - } + const target = { + uuid: targetUuid, + pbxNativeTarget: { + isa: 'PBXNativeTarget', + name: '"' + targetName + '"', + productName: '"' + targetName + '"', + productReference: productFile.fileRef, + productType: '"' + producttypeForTargettype(targetType) + '"', + buildConfigurationList: buildConfigurations.uuid, + buildPhases: [], + buildRules: [], + dependencies: [] + } }; // Target: Add to PBXNativeTarget section - this.addToPbxNativeTargetSection(target) + this.addToPbxNativeTargetSection(target); // Product: Embed (only for "extension"-type targets) if (targetType === 'app_extension') { - // Create CopyFiles phase in first target - this.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Copy Files', this.getFirstTarget().uuid, targetType) + this.addBuildPhase([], 'PBXCopyFilesBuildPhase', 'Copy Files', this.getFirstTarget().uuid, targetType); // Add product to CopyFiles phase - this.addToPbxCopyfilesBuildPhase(productFile) + this.addToPbxCopyfilesBuildPhase(productFile); - // this.addBuildPhaseToTarget(newPhase.buildPhase, this.getFirstTarget().uuid) + // this.addBuildPhaseToTarget(newPhase.buildPhase, this.getFirstTarget().uuid) } else if (targetType === 'watch2_app') { // Create CopyFiles phase in first target this.addBuildPhase( @@ -1488,7 +1596,7 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) { ); } else if (targetType === 'watch2_extension') { // Create CopyFiles phase in watch target (if exists) - var watch2Target = this.getTarget(producttypeForTargettype('watch2_app')); + const watch2Target = this.getTarget(producttypeForTargettype('watch2_app')); if (watch2Target) { this.addBuildPhase( [targetName + '.appex'], @@ -1505,7 +1613,7 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) { // Target: Add dependency for this target to other targets if (targetType === 'watch2_extension') { - var watch2Target = this.getTarget(producttypeForTargettype('watch2_app')); + const watch2Target = this.getTarget(producttypeForTargettype('watch2_app')); if (watch2Target) { this.addTargetDependency(watch2Target.uuid, [target.uuid]); } @@ -1513,15 +1621,13 @@ pbxProject.prototype.addTarget = function(name, type, subfolder) { this.addTargetDependency(this.getFirstTarget().uuid, [target.uuid]); } - // Return target on success return target; - }; // helper object creation functions -function pbxBuildFileObj(file) { - var obj = Object.create(null); +function pbxBuildFileObj (file) { + const obj = Object.create(null); obj.isa = 'PBXBuildFile'; obj.fileRef = file.fileRef; @@ -1531,11 +1637,11 @@ function pbxBuildFileObj(file) { return obj; } -function pbxFileReferenceObj(file) { - var fileObject = { - isa: "PBXFileReference", - name: "\"" + file.basename + "\"", - path: "\"" + file.path.replace(/\\/g, '/') + "\"", +function pbxFileReferenceObj (file) { + const fileObject = { + isa: 'PBXFileReference', + name: '"' + file.basename + '"', + path: '"' + file.path.replace(/\\/g, '/') + '"', sourceTree: file.sourceTree, fileEncoding: file.fileEncoding, lastKnownFileType: file.lastKnownFileType, @@ -1546,8 +1652,8 @@ function pbxFileReferenceObj(file) { return fileObject; } -function pbxGroupChild(file) { - var obj = Object.create(null); +function pbxGroupChild (file) { + const obj = Object.create(null); obj.value = file.fileRef; obj.comment = file.basename; @@ -1555,8 +1661,8 @@ function pbxGroupChild(file) { return obj; } -function pbxBuildPhaseObj(file) { - var obj = Object.create(null); +function pbxBuildPhaseObj (file) { + const obj = Object.create(null); obj.value = file.uuid; obj.comment = longComment(file); @@ -1564,10 +1670,9 @@ function pbxBuildPhaseObj(file) { return obj; } -function pbxCopyFilesBuildPhaseObj(obj, folderType, subfolderPath, phaseName) { - - // Add additional properties for 'CopyFiles' build phase - var DESTINATION_BY_TARGETTYPE = { +function pbxCopyFilesBuildPhaseObj (obj, folderType, subfolderPath, phaseName) { + // Add additional properties for 'CopyFiles' build phase + const DESTINATION_BY_TARGETTYPE = { application: 'wrapper', app_extension: 'plugins', bundle: 'wrapper', @@ -1581,8 +1686,8 @@ function pbxCopyFilesBuildPhaseObj(obj, folderType, subfolderPath, phaseName) { watch2_app: 'products_directory', watch_extension: 'plugins', watch2_extension: 'plugins' - } - var SUBFOLDERSPEC_BY_DESTINATION = { + }; + const SUBFOLDERSPEC_BY_DESTINATION = { absolute_path: 0, executables: 6, frameworks: 10, @@ -1594,7 +1699,7 @@ function pbxCopyFilesBuildPhaseObj(obj, folderType, subfolderPath, phaseName) { shared_support: 12, wrapper: 1, xpc_services: 0 - } + }; obj.name = '"' + phaseName + '"'; obj.dstPath = subfolderPath || '""'; @@ -1603,60 +1708,67 @@ function pbxCopyFilesBuildPhaseObj(obj, folderType, subfolderPath, phaseName) { return obj; } -function pbxShellScriptBuildPhaseObj(obj, options, phaseName) { +function pbxShellScriptBuildPhaseObj (obj, options, phaseName) { obj.name = '"' + phaseName + '"'; obj.inputPaths = options.inputPaths || []; obj.outputPaths = options.outputPaths || []; obj.shellPath = options.shellPath; obj.shellScript = '"' + options.shellScript.replace(/"/g, '\\"') + '"'; + // By default, runOnlyForDeploymentPostprocessing is set to 0. + // Any truthy value, it will be set to 1, including any non-empty strings. + if (options.runOnlyForDeploymentPostprocessing) { + obj.runOnlyForDeploymentPostprocessing = 1; + } + + // By default, alwaysOutOfDate is not set and treated as false. + // Any truthy value, it will be set to 1, including any non-empty strings. + if (options.alwaysOutOfDate) { + obj.alwaysOutOfDate = 1; + } + return obj; } -function pbxBuildFileComment(file) { +function pbxBuildFileComment (file) { return longComment(file); } -function pbxFileReferenceComment(file) { +function pbxFileReferenceComment (file) { return file.basename || path.basename(file.path); } -function pbxNativeTargetComment(target) { +function pbxNativeTargetComment (target) { return target.name; } -function longComment(file) { - return f("%s in %s", file.basename, file.group); +function longComment (file) { + return f('%s in %s', file.basename, file.group); } // respect path -function correctForPluginsPath(file, project) { +function correctForPluginsPath (file, project) { return correctForPath(file, project, 'Plugins'); } -function correctForResourcesPath(file, project) { +function correctForResourcesPath (file, project) { return correctForPath(file, project, 'Resources'); } -function correctForFrameworksPath(file, project) { - return correctForPath(file, project, 'Frameworks'); -} - -function correctForPath(file, project, group) { - var r_group_dir = new RegExp('^' + group + '[\\\\/]'); +function correctForPath (file, project, group) { + const r_group_dir = new RegExp('^' + group + '[\\\\/]'); - if (project.pbxGroupByName(group).path) - file.path = file.path.replace(r_group_dir, ''); + if (project.pbxGroupByName(group) && project.pbxGroupByName(group).path) { file.path = file.path.replace(r_group_dir, ''); } return file; } -function searchPathForFile(file, proj) { - var plugins = proj.pbxGroupByName('Plugins'), - pluginsPath = plugins ? plugins.path : null, - fileDir = path.dirname(file.path); +function searchPathForFile (file, proj) { + const plugins = proj.pbxGroupByName('Plugins'); + const pluginsPath = plugins ? plugins.path : null; + let fileDir = path.dirname(file.path); - if (fileDir == '.') { + if (fileDir === '.') { fileDir = ''; } else { fileDir = '/' + fileDir; @@ -1671,9 +1783,10 @@ function searchPathForFile(file, proj) { } } -function nonComments(obj) { - var keys = Object.keys(obj), - newObj = {}, i = 0; +function nonComments (obj) { + const keys = Object.keys(obj); + const newObj = {}; + let i = 0; for (i; i < keys.length; i++) { if (!COMMENT_KEY.test(keys[i])) { @@ -1684,103 +1797,87 @@ function nonComments(obj) { return newObj; } -function unquote(str) { - if (str) return str.replace(/^"(.*)"$/, "$1"); -} - - -function buildPhaseNameForIsa (isa) { - - BUILDPHASENAME_BY_ISA = { - PBXCopyFilesBuildPhase: 'Copy Files', - PBXResourcesBuildPhase: 'Resources', - PBXSourcesBuildPhase: 'Sources', - PBXFrameworksBuildPhase: 'Frameworks' - } - - return BUILDPHASENAME_BY_ISA[isa] +function unquote (str) { + if (str) return str.replace(/^"(.*)"$/, '$1'); } function producttypeForTargettype (targetType) { + const PRODUCTTYPE_BY_TARGETTYPE = { + application: 'com.apple.product-type.application', + app_extension: 'com.apple.product-type.app-extension', + bundle: 'com.apple.product-type.bundle', + command_line_tool: 'com.apple.product-type.tool', + dynamic_library: 'com.apple.product-type.library.dynamic', + framework: 'com.apple.product-type.framework', + static_library: 'com.apple.product-type.library.static', + unit_test_bundle: 'com.apple.product-type.bundle.unit-test', + watch_app: 'com.apple.product-type.application.watchapp', + watch2_app: 'com.apple.product-type.application.watchapp2', + watch_extension: 'com.apple.product-type.watchkit-extension', + watch2_extension: 'com.apple.product-type.watchkit2-extension' + }; - PRODUCTTYPE_BY_TARGETTYPE = { - application: 'com.apple.product-type.application', - app_extension: 'com.apple.product-type.app-extension', - bundle: 'com.apple.product-type.bundle', - command_line_tool: 'com.apple.product-type.tool', - dynamic_library: 'com.apple.product-type.library.dynamic', - framework: 'com.apple.product-type.framework', - static_library: 'com.apple.product-type.library.static', - unit_test_bundle: 'com.apple.product-type.bundle.unit-test', - watch_app: 'com.apple.product-type.application.watchapp', - watch2_app: 'com.apple.product-type.application.watchapp2', - watch_extension: 'com.apple.product-type.watchkit-extension', - watch2_extension: 'com.apple.product-type.watchkit2-extension' - }; - - return PRODUCTTYPE_BY_TARGETTYPE[targetType] + return PRODUCTTYPE_BY_TARGETTYPE[targetType]; } function filetypeForProducttype (productType) { + const FILETYPE_BY_PRODUCTTYPE = { + 'com.apple.product-type.application': '"wrapper.application"', + 'com.apple.product-type.app-extension': '"wrapper.app-extension"', + 'com.apple.product-type.bundle': '"wrapper.plug-in"', + 'com.apple.product-type.tool': '"compiled.mach-o.dylib"', + 'com.apple.product-type.library.dynamic': '"compiled.mach-o.dylib"', + 'com.apple.product-type.framework': '"wrapper.framework"', + 'com.apple.product-type.library.static': '"archive.ar"', + 'com.apple.product-type.bundle.unit-test': '"wrapper.cfbundle"', + 'com.apple.product-type.application.watchapp': '"wrapper.application"', + 'com.apple.product-type.application.watchapp2': '"wrapper.application"', + 'com.apple.product-type.watchkit-extension': '"wrapper.app-extension"', + 'com.apple.product-type.watchkit2-extension': '"wrapper.app-extension"' + }; - FILETYPE_BY_PRODUCTTYPE = { - 'com.apple.product-type.application': '"wrapper.application"', - 'com.apple.product-type.app-extension': '"wrapper.app-extension"', - 'com.apple.product-type.bundle': '"wrapper.plug-in"', - 'com.apple.product-type.tool': '"compiled.mach-o.dylib"', - 'com.apple.product-type.library.dynamic': '"compiled.mach-o.dylib"', - 'com.apple.product-type.framework': '"wrapper.framework"', - 'com.apple.product-type.library.static': '"archive.ar"', - 'com.apple.product-type.bundle.unit-test': '"wrapper.cfbundle"', - 'com.apple.product-type.application.watchapp': '"wrapper.application"', - 'com.apple.product-type.application.watchapp2': '"wrapper.application"', - 'com.apple.product-type.watchkit-extension': '"wrapper.app-extension"', - 'com.apple.product-type.watchkit2-extension': '"wrapper.app-extension"' - }; - - return FILETYPE_BY_PRODUCTTYPE[productType] + return FILETYPE_BY_PRODUCTTYPE[productType]; } -pbxProject.prototype.getFirstProject = function() { - +PBXProject.prototype.getFirstProject = function () { // Get pbxProject container - var pbxProjectContainer = this.pbxProjectSection(); + const pbxProjectContainer = this.pbxProjectSection(); // Get first pbxProject UUID - var firstProjectUuid = Object.keys(pbxProjectContainer)[0]; + const firstProjectUuid = Object.keys(pbxProjectContainer)[0]; // Get first pbxProject - var firstProject = pbxProjectContainer[firstProjectUuid]; + const firstProject = pbxProjectContainer[firstProjectUuid]; - return { + return { uuid: firstProjectUuid, - firstProject: firstProject - } -} + firstProject + }; +}; -pbxProject.prototype.getFirstTarget = function() { +PBXProject.prototype.getFirstTarget = function () { // Get first target's UUID - var firstTargetUuid = this.getFirstProject()['firstProject']['targets'][0].value; + const firstTargetUuid = this.getFirstProject().firstProject.targets[0].value; // Get first pbxNativeTarget - var firstTarget = this.pbxNativeTargetSection()[firstTargetUuid]; + const firstTarget = this.pbxNativeTargetSection()[firstTargetUuid]; return { uuid: firstTargetUuid, - firstTarget: firstTarget - } -} + firstTarget + }; +}; -pbxProject.prototype.getTarget = function(productType) { +PBXProject.prototype.getTarget = function (productType) { // Find target by product type - var targets = this.getFirstProject()['firstProject']['targets']; - var nativeTargets = this.pbxNativeTargetSection(); - for (var i = 0; i < targets.length; i++) { - var target = targets[i]; - var targetUuid = target.value; - if (nativeTargets[targetUuid]['productType'] === '"' + productType + '"') { + const targets = this.getFirstProject().firstProject.targets; + const nativeTargets = this.pbxNativeTargetSection(); + for (let i = 0; i < targets.length; i++) { + const target = targets[i]; + const targetUuid = target.value; + if (nativeTargets[targetUuid].productType === '"' + productType + '"') { // Get pbxNativeTarget - var nativeTarget = this.pbxNativeTargetSection()[targetUuid]; + const nativeTarget = this.pbxNativeTargetSection()[targetUuid]; return { uuid: targetUuid, target: nativeTarget @@ -1789,258 +1886,268 @@ pbxProject.prototype.getTarget = function(productType) { } return null; -} +}; -/*** NEW ***/ +/** * NEW ***/ -pbxProject.prototype.addToPbxGroupType = function (file, groupKey, groupType) { - var group = this.getPBXGroupByKeyAndType(groupKey, groupType); +PBXProject.prototype.addToPbxGroupType = function (file, groupKey, groupType) { + const group = this.getPBXGroupByKeyAndType(groupKey, groupType); if (group && group.children !== undefined) { if (typeof file === 'string') { - //Group Key - var childGroup = { - value:file, + // Group Key + const childGroup = { + value: file }; if (this.getPBXGroupByKey(file)) { childGroup.comment = this.getPBXGroupByKey(file).name; - } - else if (this.getPBXVariantGroupByKey(file)) { + } else if (this.getPBXVariantGroupByKey(file)) { childGroup.comment = this.getPBXVariantGroupByKey(file).name; } group.children.push(childGroup); - } - else { - //File Object + } else { + // File Object group.children.push(pbxGroupChild(file)); } } -} +}; -pbxProject.prototype.addToPbxVariantGroup = function (file, groupKey) { +PBXProject.prototype.addToPbxVariantGroup = function (file, groupKey) { this.addToPbxGroupType(file, groupKey, 'PBXVariantGroup'); -} +}; -pbxProject.prototype.addToPbxGroup = function (file, groupKey) { +PBXProject.prototype.addToPbxGroup = function (file, groupKey) { this.addToPbxGroupType(file, groupKey, 'PBXGroup'); -} - - +}; -pbxProject.prototype.pbxCreateGroupWithType = function(name, pathName, groupType) { - //Create object - var model = { +PBXProject.prototype.pbxCreateGroupWithType = function (name, pathName, groupType) { + // Create object + const model = { isa: '"' + groupType + '"', children: [], - name: name, + name, sourceTree: '""' }; if (pathName) model.path = pathName; - var key = this.generateUuid(); + const key = this.generateUuid(); + + // Create comment + const commendId = key + '_comment'; - //Create comment - var commendId = key + '_comment'; + // Reject object keys that shouldn't be writable. + if (RESTRICTED_OBJECT_KEYS.has(groupType)) { + throw new Error(`"${groupType}" is restricted and cannot be used as a group type.`); + } - //add obj and commentObj to groups; - var groups = this.hash.project.objects[groupType]; + // add obj and commentObj to groups; + let groups = this.hash.project.objects[groupType]; if (!groups) { - groups = this.hash.project.objects[groupType] = new Object(); + groups = this.hash.project.objects[groupType] = {}; } groups[commendId] = name; groups[key] = model; return key; -} +}; -pbxProject.prototype.pbxCreateVariantGroup = function(name) { - return this.pbxCreateGroupWithType(name, undefined, 'PBXVariantGroup') -} +PBXProject.prototype.pbxCreateVariantGroup = function (name) { + return this.pbxCreateGroupWithType(name, undefined, 'PBXVariantGroup'); +}; -pbxProject.prototype.pbxCreateGroup = function(name, pathName) { +PBXProject.prototype.pbxCreateGroup = function (name, pathName) { return this.pbxCreateGroupWithType(name, pathName, 'PBXGroup'); -} - - +}; -pbxProject.prototype.removeFromPbxGroupAndType = function (file, groupKey, groupType) { - var group = this.getPBXGroupByKeyAndType(groupKey, groupType); +PBXProject.prototype.removeFromPbxGroupAndType = function (file, groupKey, groupType) { + const group = this.getPBXGroupByKeyAndType(groupKey, groupType); if (group) { - var groupChildren = group.children, i; - for(i in groupChildren) { - if(pbxGroupChild(file).value == groupChildren[i].value && - pbxGroupChild(file).comment == groupChildren[i].comment) { + const groupChildren = group.children; + for (const i in groupChildren) { + if (pbxGroupChild(file).value === groupChildren[i].value && + pbxGroupChild(file).comment === groupChildren[i].comment) { groupChildren.splice(i, 1); break; } } } -} +}; -pbxProject.prototype.removeFromPbxGroup = function (file, groupKey) { +PBXProject.prototype.removeFromPbxGroup = function (file, groupKey) { this.removeFromPbxGroupAndType(file, groupKey, 'PBXGroup'); -} +}; -pbxProject.prototype.removeFromPbxVariantGroup = function (file, groupKey) { +PBXProject.prototype.removeFromPbxVariantGroup = function (file, groupKey) { this.removeFromPbxGroupAndType(file, groupKey, 'PBXVariantGroup'); -} - - +}; -pbxProject.prototype.getPBXGroupByKeyAndType = function(key, groupType) { +PBXProject.prototype.getPBXGroupByKeyAndType = function (key, groupType) { return this.hash.project.objects[groupType][key]; }; -pbxProject.prototype.getPBXGroupByKey = function(key) { - return this.hash.project.objects['PBXGroup'][key]; +PBXProject.prototype.getPBXGroupByKey = function (key) { + return this.hash.project.objects.PBXGroup[key]; }; -pbxProject.prototype.getPBXVariantGroupByKey = function(key) { - return this.hash.project.objects['PBXVariantGroup'][key]; +PBXProject.prototype.getPBXVariantGroupByKey = function (key) { + return this.hash.project.objects.PBXVariantGroup[key]; }; +PBXProject.prototype.findPBXGroupKeyAndType = function (criteria, groupType) { + const groups = this.hash.project.objects[groupType]; + let target; - -pbxProject.prototype.findPBXGroupKeyAndType = function(criteria, groupType) { - var groups = this.hash.project.objects[groupType]; - var target; - - for (var key in groups) { + for (const key in groups) { // only look for comments if (COMMENT_KEY.test(key)) continue; - var group = groups[key]; + const group = groups[key]; if (criteria && criteria.path && criteria.name) { if (criteria.path === group.path && criteria.name === group.name) { target = key; - break + break; } - } - else if (criteria && criteria.path) { + } else if (criteria && criteria.path) { if (criteria.path === group.path) { target = key; - break + break; } - } - else if (criteria && criteria.name) { + } else if (criteria && criteria.name) { if (criteria.name === group.name) { target = key; - break + break; } } } return target; -} +}; -pbxProject.prototype.findPBXGroupKey = function(criteria) { +PBXProject.prototype.findPBXGroupKey = function (criteria) { return this.findPBXGroupKeyAndType(criteria, 'PBXGroup'); -} +}; -pbxProject.prototype.findPBXVariantGroupKey = function(criteria) { +PBXProject.prototype.findPBXVariantGroupKey = function (criteria) { return this.findPBXGroupKeyAndType(criteria, 'PBXVariantGroup'); -} +}; -pbxProject.prototype.addLocalizationVariantGroup = function(name) { - var groupKey = this.pbxCreateVariantGroup(name); +PBXProject.prototype.addLocalizationVariantGroup = function (name) { + const groupKey = this.pbxCreateVariantGroup(name); - var resourceGroupKey = this.findPBXGroupKey({name: 'Resources'}); + const resourceGroupKey = this.findPBXGroupKey({ name: 'Resources' }); this.addToPbxGroup(groupKey, resourceGroupKey); - var localizationVariantGroup = { + const localizationVariantGroup = { uuid: this.generateUuid(), fileRef: groupKey, basename: name - } - this.addToPbxBuildFileSection(localizationVariantGroup); // PBXBuildFile - this.addToPbxResourcesBuildPhase(localizationVariantGroup); //PBXResourcesBuildPhase + }; + this.addToPbxBuildFileSection(localizationVariantGroup); // PBXBuildFile + this.addToPbxResourcesBuildPhase(localizationVariantGroup); // PBXResourcesBuildPhase return localizationVariantGroup; }; -pbxProject.prototype.addKnownRegion = function (name) { - if (!this.pbxProjectSection()[this.getFirstProject()['uuid']]['knownRegions']) { - this.pbxProjectSection()[this.getFirstProject()['uuid']]['knownRegions'] = []; - } - if (!this.hasKnownRegion(name)) { - this.pbxProjectSection()[this.getFirstProject()['uuid']]['knownRegions'].push(name); - } -} +PBXProject.prototype.addKnownRegion = function (name) { + if (!this.pbxProjectSection()[this.getFirstProject().uuid].knownRegions) { + this.pbxProjectSection()[this.getFirstProject().uuid].knownRegions = []; + } + if (!this.hasKnownRegion(name)) { + this.pbxProjectSection()[this.getFirstProject().uuid].knownRegions.push(name); + } +}; -pbxProject.prototype.removeKnownRegion = function (name) { - var regions = this.pbxProjectSection()[this.getFirstProject()['uuid']]['knownRegions']; - if (regions) { - for (var i = 0; i < regions.length; i++) { - if (regions[i] === name) { - regions.splice(i, 1); - break; - } - } - this.pbxProjectSection()[this.getFirstProject()['uuid']]['knownRegions'] = regions; - } -} +PBXProject.prototype.removeKnownRegion = function (name) { + const regions = this.pbxProjectSection()[this.getFirstProject().uuid].knownRegions; + if (regions) { + for (let i = 0; i < regions.length; i++) { + if (regions[i] === name) { + regions.splice(i, 1); + break; + } + } + this.pbxProjectSection()[this.getFirstProject().uuid].knownRegions = regions; + } +}; -pbxProject.prototype.hasKnownRegion = function (name) { - var regions = this.pbxProjectSection()[this.getFirstProject()['uuid']]['knownRegions']; - if (regions) { - for (var i in regions) { - if (regions[i] === name) { - return true; - } +PBXProject.prototype.hasKnownRegion = function (name) { + const regions = this.pbxProjectSection()[this.getFirstProject().uuid].knownRegions; + if (regions) { + for (const i in regions) { + if (regions[i] === name) { + return true; + } + } } - } - return false; -} + return false; +}; -pbxProject.prototype.getPBXObject = function(name) { +PBXProject.prototype.getPBXObject = function (name) { return this.hash.project.objects[name]; -} - - +}; -pbxProject.prototype.addFile = function (path, group, opt) { - var file = new pbxFile(path, opt); +PBXProject.prototype.addFile = function (path, group, opt) { + const file = new PBXFile(path, opt); // null is better for early errors if (this.hasFile(file.path)) return null; file.fileRef = this.generateUuid(); - this.addToPbxFileReferenceSection(file); // PBXFileReference + this.addToPbxFileReferenceSection(file); // PBXFileReference if (this.getPBXGroupByKey(group)) { - this.addToPbxGroup(file, group); // PBXGroup - } - else if (this.getPBXVariantGroupByKey(group)) { - this.addToPbxVariantGroup(file, group); // PBXVariantGroup + this.addToPbxGroup(file, group); // PBXGroup + } else if (this.getPBXVariantGroupByKey(group)) { + this.addToPbxVariantGroup(file, group); // PBXVariantGroup } return file; -} +}; -pbxProject.prototype.removeFile = function (path, group, opt) { - var file = new pbxFile(path, opt); +PBXProject.prototype.removeFile = function (path, group, opt) { + const file = new PBXFile(path, opt); - this.removeFromPbxFileReferenceSection(file); // PBXFileReference + this.removeFromPbxFileReferenceSection(file); // PBXFileReference if (this.getPBXGroupByKey(group)) { - this.removeFromPbxGroup(file, group); // PBXGroup - } - else if (this.getPBXVariantGroupByKey(group)) { - this.removeFromPbxVariantGroup(file, group); // PBXVariantGroup + this.removeFromPbxGroup(file, group); // PBXGroup + } else if (this.getPBXVariantGroupByKey(group)) { + this.removeFromPbxVariantGroup(file, group); // PBXVariantGroup } return file; -} +}; + +PBXProject.prototype.getBuildProperty = function (prop, build, targetName) { + let target; + const validConfigs = []; + + if (targetName) { + const target = this.pbxTargetByName(targetName); + const targetBuildConfigs = target && target.buildConfigurationList; + + const xcConfigList = this.pbxXCConfigurationList(); + + // Collect the UUID's from the configuration of our target + for (const configName in xcConfigList) { + if (!COMMENT_KEY.test(configName) && targetBuildConfigs === configName) { + const buildVariants = xcConfigList[configName].buildConfigurations; + for (const item of buildVariants) { + validConfigs.push(item.value); + } + break; + } + } + } -pbxProject.prototype.getBuildProperty = function(prop, build) { - var target; - var configs = this.pbxXCBuildConfigurationSection(); - for (var configName in configs) { + const configs = this.pbxXCBuildConfigurationSection(); + for (const configName in configs) { if (!COMMENT_KEY.test(configName)) { - var config = configs[configName]; - if ( (build && config.name === build) || (build === undefined) ) { + if (targetName && !validConfigs.includes(configName)) continue; + const config = configs[configName]; + if ((build && config.name === build) || (build === undefined)) { if (config.buildSettings[prop] !== undefined) { target = config.buildSettings[prop]; } @@ -2048,23 +2155,23 @@ pbxProject.prototype.getBuildProperty = function(prop, build) { } } return target; -} +}; -pbxProject.prototype.getBuildConfigByName = function(name) { - var target = {}; - var configs = this.pbxXCBuildConfigurationSection(); - for (var configName in configs) { +PBXProject.prototype.getBuildConfigByName = function (name) { + const target = {}; + const configs = this.pbxXCBuildConfigurationSection(); + for (const configName in configs) { if (!COMMENT_KEY.test(configName)) { - var config = configs[configName]; - if (config.name === name) { + const config = configs[configName]; + if (config.name === name) { target[configName] = config; } } } return target; -} +}; -pbxProject.prototype.addDataModelDocument = function(filePath, group, opt) { +PBXProject.prototype.addDataModelDocument = function (filePath, group, opt) { if (!group) { group = 'Resources'; } @@ -2072,7 +2179,7 @@ pbxProject.prototype.addDataModelDocument = function(filePath, group, opt) { group = this.findPBXGroupKey({ name: group }); } - var file = new pbxFile(filePath, opt); + const file = new PBXFile(filePath, opt); if (!file || this.hasFile(file.path)) return null; @@ -2088,18 +2195,18 @@ pbxProject.prototype.addDataModelDocument = function(filePath, group, opt) { this.addToPbxSourcesBuildPhase(file); file.models = []; - var currentVersionName; - var modelFiles = fs.readdirSync(file.path); - for (var index in modelFiles) { - var modelFileName = modelFiles[index]; - var modelFilePath = path.join(filePath, modelFileName); + let currentVersionName; + const modelFiles = fs.readdirSync(file.path); + for (const index in modelFiles) { + const modelFileName = modelFiles[index]; + const modelFilePath = path.join(filePath, modelFileName); - if (modelFileName == '.xccurrentversion') { + if (modelFileName === '.xccurrentversion') { currentVersionName = plist.readFileSync(modelFilePath)._XCCurrentVersionName; continue; } - var modelFile = new pbxFile(modelFilePath); + const modelFile = new PBXFile(modelFilePath); modelFile.fileRef = this.generateUuid(); this.addToPbxFileReferenceSection(modelFile); @@ -2118,27 +2225,33 @@ pbxProject.prototype.addDataModelDocument = function(filePath, group, opt) { this.addToXcVersionGroupSection(file); return file; -} +}; -pbxProject.prototype.addTargetAttribute = function(prop, value, target) { - var attributes = this.getFirstProject()['firstProject']['attributes']; - if (attributes['TargetAttributes'] === undefined) { - attributes['TargetAttributes'] = {}; +PBXProject.prototype.addTargetAttribute = function (prop, value, target) { + const attributes = this.getFirstProject().firstProject.attributes; + if (attributes.TargetAttributes === undefined) { + attributes.TargetAttributes = {}; } target = target || this.getFirstTarget(); - if (attributes['TargetAttributes'][target.uuid] === undefined) { - attributes['TargetAttributes'][target.uuid] = {}; + + // Reject object keys that shouldn't be writable. + if (RESTRICTED_OBJECT_KEYS.has(target.uuid)) { + throw new Error(`"${target.uuid}" is restricted and cannot be used as a uuid.`); } - attributes['TargetAttributes'][target.uuid][prop] = value; -} -pbxProject.prototype.removeTargetAttribute = function(prop, target) { - var attributes = this.getFirstProject()['firstProject']['attributes']; + if (attributes.TargetAttributes[target.uuid] === undefined) { + attributes.TargetAttributes[target.uuid] = {}; + } + attributes.TargetAttributes[target.uuid][prop] = value; +}; + +PBXProject.prototype.removeTargetAttribute = function (prop, target) { + const attributes = this.getFirstProject().firstProject.attributes; target = target || this.getFirstTarget(); - if (attributes['TargetAttributes'] && - attributes['TargetAttributes'][target.uuid]) { - delete attributes['TargetAttributes'][target.uuid][prop]; + if (attributes.TargetAttributes && + attributes.TargetAttributes[target.uuid]) { + delete attributes.TargetAttributes[target.uuid][prop]; } -} +}; -module.exports = pbxProject; +module.exports = PBXProject; diff --git a/lib/pbxWriter.js b/lib/pbxWriter.js index d297bc79..b5d52731 100644 --- a/lib/pbxWriter.js +++ b/lib/pbxWriter.js @@ -1,111 +1,107 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var pbxProj = require('./pbxProject'), - util = require('util'), - f = util.format, - INDENT = '\t', - COMMENT_KEY = /_comment$/, - QUOTED = /^"(.*)"$/, - EventEmitter = require('events').EventEmitter +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const util = require('util'); +const f = util.format; +const INDENT = '\t'; +const COMMENT_KEY = /_comment$/; +const EventEmitter = require('events').EventEmitter; // indentation -function i(x) { - if (x <=0) - return ''; - else - return INDENT + i(x-1); +function i (x) { + if (x <= 0) { return ''; } else { return INDENT + i(x - 1); } } -function comment(key, parent) { - var text = parent[key + '_comment']; +function comment (key, parent) { + const text = parent[key + '_comment']; - if (text) - return text; - else - return null; + if (text) { return text; } else { return null; } } // copied from underscore -function isObject(obj) { - return obj === Object(obj) +function isObject (obj) { + return obj === Object(obj); } -function isArray(obj) { - return Array.isArray(obj) +function isArray (obj) { + return Array.isArray(obj); } -function pbxWriter(contents, options) { +function pbxWriter (contents, options) { if (!options) { - options = {} + options = {}; } if (options.omitEmptyValues === undefined) { - options.omitEmptyValues = false + options.omitEmptyValues = false; } this.contents = contents; this.sync = false; this.indentLevel = 0; - this.omitEmptyValues = options.omitEmptyValues + this.omitEmptyValues = options.omitEmptyValues; } util.inherits(pbxWriter, EventEmitter); pbxWriter.prototype.write = function (str) { - var fmt = f.apply(null, arguments); + const fmt = f.apply(null, arguments); if (this.sync) { - this.buffer += f("%s%s", i(this.indentLevel), fmt); + this.buffer += f('%s%s', i(this.indentLevel), fmt); } else { // do stream write } -} +}; pbxWriter.prototype.writeFlush = function (str) { - var oldIndent = this.indentLevel; + const oldIndent = this.indentLevel; this.indentLevel = 0; - this.write.apply(this, arguments) + this.write.apply(this, arguments); this.indentLevel = oldIndent; -} +}; pbxWriter.prototype.writeSync = function () { this.sync = true; - this.buffer = ""; + this.buffer = ''; this.writeHeadComment(); this.writeProject(); return this.buffer; -} +}; pbxWriter.prototype.writeHeadComment = function () { if (this.contents.headComment) { - this.write("// %s\n", this.contents.headComment) + this.write('// %s\n', this.contents.headComment); } -} +}; pbxWriter.prototype.writeProject = function () { - var proj = this.contents.project, - key, cmt, obj; + const proj = this.contents.project; + let key; + let cmt; + let obj; - this.write("{\n") + this.write('{\n'); if (proj) { this.indentLevel++; @@ -118,36 +114,36 @@ pbxWriter.prototype.writeProject = function () { obj = proj[key]; if (isArray(obj)) { - this.writeArray(obj, key) + this.writeArray(obj, key); } else if (isObject(obj)) { - this.write("%s = {\n", key); + this.write('%s = {\n', key); this.indentLevel++; if (key === 'objects') { - this.writeObjectsSections(obj) + this.writeObjectsSections(obj); } else { - this.writeObject(obj) + this.writeObject(obj); } this.indentLevel--; - this.write("};\n"); + this.write('};\n'); } else if (this.omitEmptyValues && (obj === undefined || obj === null)) { continue; } else if (cmt) { - this.write("%s = %s /* %s */;\n", key, obj, cmt) + this.write('%s = %s /* %s */;\n', key, obj, cmt); } else { - this.write("%s = %s;\n", key, obj) + this.write('%s = %s;\n', key, obj); } } this.indentLevel--; } - this.write("}\n") -} + this.write('}\n'); +}; pbxWriter.prototype.writeObject = function (object) { - var key, obj, cmt; + let key, obj, cmt; for (key in object) { if (COMMENT_KEY.test(key)) continue; @@ -156,32 +152,32 @@ pbxWriter.prototype.writeObject = function (object) { obj = object[key]; if (isArray(obj)) { - this.writeArray(obj, key) + this.writeArray(obj, key); } else if (isObject(obj)) { - this.write("%s = {\n", key); + this.write('%s = {\n', key); this.indentLevel++; - this.writeObject(obj) + this.writeObject(obj); this.indentLevel--; - this.write("};\n"); + this.write('};\n'); } else { if (this.omitEmptyValues && (obj === undefined || obj === null)) { continue; } else if (cmt) { - this.write("%s = %s /* %s */;\n", key, obj, cmt) + this.write('%s = %s /* %s */;\n', key, obj, cmt); } else { - this.write("%s = %s;\n", key, obj) + this.write('%s = %s;\n', key, obj); } } } -} +}; pbxWriter.prototype.writeObjectsSections = function (objects) { - var key, obj; + let key, obj; for (key in objects) { - this.writeFlush("\n") + this.writeFlush('\n'); obj = objects[key]; @@ -193,16 +189,16 @@ pbxWriter.prototype.writeObjectsSections = function (objects) { this.writeSectionComment(key, false); } } -} +}; pbxWriter.prototype.writeArray = function (arr, name) { - var i, entry; + let i, entry; - this.write("%s = (\n", name); + this.write('%s = (\n', name); this.indentLevel++; - for (i=0; i < arr.length; i++) { - entry = arr[i] + for (i = 0; i < arr.length; i++) { + entry = arr[i]; if (entry.value && entry.comment) { this.write('%s /* %s */,\n', entry.value, entry.comment); @@ -220,57 +216,57 @@ pbxWriter.prototype.writeArray = function (arr, name) { } this.indentLevel--; - this.write(");\n"); -} + this.write(');\n'); +}; pbxWriter.prototype.writeSectionComment = function (name, begin) { if (begin) { - this.writeFlush("/* Begin %s section */\n", name) + this.writeFlush('/* Begin %s section */\n', name); } else { // end - this.writeFlush("/* End %s section */\n", name) + this.writeFlush('/* End %s section */\n', name); } -} +}; pbxWriter.prototype.writeSection = function (section) { - var key, obj, cmt; + let key, obj, cmt; // section should only contain objects for (key in section) { if (COMMENT_KEY.test(key)) continue; cmt = comment(key, section); - obj = section[key] + obj = section[key]; - if (obj.isa == 'PBXBuildFile' || obj.isa == 'PBXFileReference') { + if (obj.isa === 'PBXBuildFile' || obj.isa === 'PBXFileReference') { this.writeInlineObject(key, cmt, obj); } else { if (cmt) { - this.write("%s /* %s */ = {\n", key, cmt); + this.write('%s /* %s */ = {\n', key, cmt); } else { - this.write("%s = {\n", key); + this.write('%s = {\n', key); } - this.indentLevel++ + this.indentLevel++; - this.writeObject(obj) + this.writeObject(obj); - this.indentLevel-- - this.write("};\n"); + this.indentLevel--; + this.write('};\n'); } } -} +}; pbxWriter.prototype.writeInlineObject = function (n, d, r) { - var output = []; - var self = this + const output = []; + const self = this; - var inlineObjectHelper = function (name, desc, ref) { - var key, cmt, obj; + const inlineObjectHelper = function (name, desc, ref) { + let key, cmt, obj; if (desc) { - output.push(f("%s /* %s */ = {", name, desc)); + output.push(f('%s /* %s */ = {', name, desc)); } else { - output.push(f("%s = {", name)); + output.push(f('%s = {', name)); } for (key in ref) { @@ -280,30 +276,30 @@ pbxWriter.prototype.writeInlineObject = function (n, d, r) { obj = ref[key]; if (isArray(obj)) { - output.push(f("%s = (", key)); + output.push(f('%s = (', key)); - for (var i=0; i < obj.length; i++) { - output.push(f("%s, ", obj[i])) + for (let i = 0; i < obj.length; i++) { + output.push(f('%s, ', obj[i])); } - output.push("); "); + output.push('); '); } else if (isObject(obj)) { - inlineObjectHelper(key, cmt, obj) + inlineObjectHelper(key, cmt, obj); } else if (self.omitEmptyValues && (obj === undefined || obj === null)) { continue; } else if (cmt) { - output.push(f("%s = %s /* %s */; ", key, obj, cmt)) + output.push(f('%s = %s /* %s */; ', key, obj, cmt)); } else { - output.push(f("%s = %s; ", key, obj)) + output.push(f('%s = %s; ', key, obj)); } } - output.push("}; "); - } + output.push('}; '); + }; inlineObjectHelper(n, d, r); - this.write("%s\n", output.join('').trim()); -} + this.write('%s\n', output.join('').trim()); +}; module.exports = pbxWriter; diff --git a/licence_checker.yml b/licence_checker.yml new file mode 100644 index 00000000..6456f794 --- /dev/null +++ b/licence_checker.yml @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Empty for the release audit workflow. +# The `license-config` is required even if there are no custom configs diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..71f3431a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3436 @@ +{ + "name": "xcode", + "version": "4.0.0-dev.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "xcode", + "version": "4.0.0-dev.0", + "license": "Apache-2.0", + "dependencies": { + "simple-plist": "^1.3.1" + }, + "devDependencies": { + "@cordova/eslint-config": "^6.0.1", + "pegjs": "^0.10.0" + }, + "engines": { + "node": ">=14.17.0" + } + }, + "node_modules/@cordova/eslint-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@cordova/eslint-config/-/eslint-config-6.0.1.tgz", + "integrity": "sha512-+PEHLeSGE53E85cPTZFveaO9cCaZvC13q443TkMLFJneeMePaXuM8alUZo7LrTRGVCj1sM/pMTIeaEqEEfPxuQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "eslint": "^9.31.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-n": "^17.21.0", + "eslint-plugin-promise": "^7.2.1", + "globals": "^16.3.0" + }, + "engines": { + "node": ">=20.9.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.12.tgz", + "integrity": "sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bplist-creator": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.1.0.tgz", + "integrity": "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==", + "license": "MIT", + "dependencies": { + "stream-buffers": "2.2.x" + } + }, + "node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "license": "MIT", + "dependencies": { + "big-integer": "1.6.x" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.23.0.tgz", + "integrity": "sha512-yJN/BOOLxcOW2aQgeif9mSnaUB8KtvmMMp56oA1kx1CRfBKbhZm2pJ+NBY+3eOboHxix8lfjWpHE0Ei5U8RbSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-compat-utils/node_modules/semver": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz", + "integrity": "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.16.1", + "resolve": "^2.0.0-next.6" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.13.0.tgz", + "integrity": "sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-es-x": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", + "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.11.0", + "eslint-compat-utils": "^0.5.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-n": { + "version": "17.24.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.24.0.tgz", + "integrity": "sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.5.0", + "enhanced-resolve": "^5.17.1", + "eslint-plugin-es-x": "^7.8.0", + "get-tsconfig": "^4.8.1", + "globals": "^15.11.0", + "globrex": "^0.1.2", + "ignore": "^5.3.2", + "semver": "^7.6.3", + "ts-declaration-location": "^1.0.6" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": ">=8.23.0" + } + }, + "node_modules/eslint-plugin-n/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz", + "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.3.0.tgz", + "integrity": "sha512-6uGiOR0INuujr6PEQmeSSP7GbIMJ/ebEXXiEzb/nOj68LknH5Pxzb/AbZivmr6VE6TkTE8rTjRK9zhKpK6HsRA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true, + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/pegjs": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz", + "integrity": "sha512-qI5+oFNEGi3L5HAxDwN2LA4Gg7irF70Zs25edhjld9QemOgp0CbvMtbFcMvFtEo1OityPrcCzkQFB8JP/hxgow==", + "dev": true, + "license": "MIT", + "bin": { + "pegjs": "bin/pegjs" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "license": "MIT", + "dependencies": { + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "license": "Unlicense", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/ts-declaration-location": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz", + "integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==", + "dev": true, + "funding": [ + { + "type": "ko-fi", + "url": "https://ko-fi.com/rebeccastevens" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/ts-declaration-location" + } + ], + "license": "BSD-3-Clause", + "dependencies": { + "picomatch": "^4.0.2" + }, + "peerDependencies": { + "typescript": ">=4.0.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index 5b50c20f..1374c9de 100644 --- a/package.json +++ b/package.json @@ -2,47 +2,25 @@ "author": "Apache Software Foundation", "name": "xcode", "description": "parser for xcodeproj/project.pbxproj files", - "version": "2.1.0", + "version": "4.0.0-dev.0", "main": "index.js", - "repository": { - "url": "https://github.com/apache/cordova-node-xcode.git" - }, + "repository": "github:apache/cordova-node-xcode", + "bugs": "https://github.com/apache/cordova-node-xcode/issues", "engines": { - "node": ">=6.0.0" + "node": ">=14.17.0" }, "dependencies": { - "simple-plist": "^1.0.0", - "uuid": "^3.3.2" + "simple-plist": "^1.3.1" }, "devDependencies": { - "nodeunit": "^0.11.3", + "@cordova/eslint-config": "^6.0.1", "pegjs": "^0.10.0" }, "scripts": { - "pegjs": "node_modules/.bin/pegjs lib/parser/pbxproj.pegjs", - "test": "node_modules/.bin/nodeunit test/parser test" + "build": "node bin/generate-pbxproj-parser.js", + "lint": "eslint .", + "lint:fix": "npm run lint -- --fix", + "test": "npm run lint && node --test --experimental-test-coverage --test-reporter=spec --test-reporter=lcov --test-reporter-destination=stdout --test-reporter-destination=lcov.info" }, - "license": "Apache-2.0", - "contributors": [ - { - "name": "Andrew Lunny", - "email": "alunny@gmail.com" - }, - { - "name": "Anis Kadri" - }, - { - "name": "Mike Reinstein" - }, - { - "name": "Filip Maj" - }, - { - "name": "Brett Rudd", - "email": "goya@apache.org" - }, - { - "name": "Bob Easterday" - } - ] + "license": "Apache-2.0" } diff --git a/test/BuildSettings.js b/test/BuildSettings.js index 213f5758..702ef5e9 100644 --- a/test/BuildSettings.js +++ b/test/BuildSettings.js @@ -1,58 +1,58 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); + http://www.apache.org/licenses/LICENSE-2.0 -function cleanHash() { - return JSON.parse(fullProjectStr); -} + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); +function cleanHash () { + return JSON.parse(fullProjectStr); } -var PRODUCT_NAME = '"KitchenSinktablet"'; +const PRODUCT_NAME = '"KitchenSinktablet"'; -exports.addAndRemoveToFromBuildSettings = { - 'add should add the build setting to each configuration section':function(test) { - var buildSetting = 'some/buildSetting'; - var value = 'some/buildSetting'; +describe('addAndRemoveToFromBuildSettings', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + it('add should add the build setting to each configuration section', () => { + const buildSetting = 'some/buildSetting'; + const value = 'some/buildSetting'; proj.addToBuildSettings(buildSetting, value); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - test.ok(config[ref].buildSettings[buildSetting] === value); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + assert.ok(config[ref].buildSettings[buildSetting] === value); } - test.done(); - }, - 'remove should remove from the build settings in each configuration section':function(test) { - var buildSetting = 'some/buildSetting'; + }); + it('remove should remove from the build settings in each configuration section', () => { + const buildSetting = 'some/buildSetting'; proj.addToBuildSettings(buildSetting, 'some/buildSetting'); proj.removeFromBuildSettings(buildSetting); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - test.ok(!config[ref].buildSettings.hasOwnProperty(buildSetting)); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const buildSettings = config[ref].buildSettings; + assert.ok(!Object.prototype.hasOwnProperty.call(buildSettings, buildSetting)); } - test.done(); - } -} + }); +}); diff --git a/test/FrameworkSearchPaths.js b/test/FrameworkSearchPaths.js index b709f3ab..3c698921 100644 --- a/test/FrameworkSearchPaths.js +++ b/test/FrameworkSearchPaths.js @@ -1,63 +1,64 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -var pbxFile = { - path:'some/path/include', - dirname: 'some/path', - customFramework: true -} -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +const pbxFile = { + path: 'some/path/include', + dirname: 'some/path', + customFramework: true +}; + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +const PRODUCT_NAME = '"KitchenSinktablet"'; -var PRODUCT_NAME = '"KitchenSinktablet"'; +describe('addAndRemoveToFromFrameworkSearchPaths', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.addAndRemoveToFromFrameworkSearchPaths = { - 'add should add the path to each configuration section':function(test) { + it('add should add the path to each configuration section', () => { proj.addToFrameworkSearchPaths(pbxFile); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.FRAMEWORK_SEARCH_PATHS; - test.ok(lib[1].indexOf('some/path') > -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.FRAMEWORK_SEARCH_PATHS; + assert.ok(lib[1].indexOf('some/path') > -1); } - test.done(); - }, - 'remove should remove from the path to each configuration section':function(test) { + }); + it('remove should remove from the path to each configuration section', () => { proj.addToFrameworkSearchPaths(pbxFile); proj.removeFromFrameworkSearchPaths(pbxFile); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.FRAMEWORK_SEARCH_PATHS; - test.ok(lib.length === 1); - test.ok(lib[0].indexOf('some/path') == -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.FRAMEWORK_SEARCH_PATHS; + assert.ok(lib.length === 1); + assert.ok(lib[0].indexOf('some/path') === -1); } - test.done(); - } -} + }); +}); diff --git a/test/HeaderSearchPaths.js b/test/HeaderSearchPaths.js index 998fd8ba..415699bb 100644 --- a/test/HeaderSearchPaths.js +++ b/test/HeaderSearchPaths.js @@ -1,76 +1,75 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); + http://www.apache.org/licenses/LICENSE-2.0 -function cleanHash() { + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +const PRODUCT_NAME = '"KitchenSinktablet"'; -var PRODUCT_NAME = '"KitchenSinktablet"'; +describe('addAndRemoveToFromHeaderSearchPaths', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.addAndRemoveToFromHeaderSearchPaths = { - 'add should add the path to each configuration section':function(test) { + it('add should add the path to each configuration section', () => { proj.addToHeaderSearchPaths({ - path:'some/path/include' + path: 'some/path/include' }); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.HEADER_SEARCH_PATHS; - test.ok(lib[1].indexOf('$(SRCROOT)/KitchenSinktablet/some/path') > -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.HEADER_SEARCH_PATHS; + assert.ok(lib[1].indexOf('$(SRCROOT)/KitchenSinktablet/some/path') > -1); } - test.done(); - }, - 'add should not mangle string arguments and add to each config section':function(test) { - var includePath = '../../some/path'; + }); + it('add should not mangle string arguments and add to each config section', () => { + const includePath = '../../some/path'; proj.addToHeaderSearchPaths(includePath); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.HEADER_SEARCH_PATHS; - test.ok(lib[1].indexOf(includePath) > -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.HEADER_SEARCH_PATHS; + assert.ok(lib[1].indexOf(includePath) > -1); } - test.done(); - }, - 'remove should remove from the path to each configuration section':function(test) { - var libPath = 'some/path/include'; + }); + it('remove should remove from the path to each configuration section', () => { + const libPath = 'some/path/include'; proj.addToHeaderSearchPaths({ - path:libPath + path: libPath }); proj.removeFromHeaderSearchPaths({ - path:libPath + path: libPath }); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.HEADER_SEARCH_PATHS; - test.ok(lib.length === 1); - test.ok(lib[0].indexOf('$(SRCROOT)/KitchenSinktablet/some/path/include') == -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.HEADER_SEARCH_PATHS; + assert.ok(lib.length === 1); + assert.ok(lib[0].indexOf('$(SRCROOT)/KitchenSinktablet/some/path/include') === -1); } - test.done(); - } -} + }); +}); diff --git a/test/LibrarySearchPaths.js b/test/LibrarySearchPaths.js index 6788e103..31583c8b 100644 --- a/test/LibrarySearchPaths.js +++ b/test/LibrarySearchPaths.js @@ -1,76 +1,75 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); + http://www.apache.org/licenses/LICENSE-2.0 -function cleanHash() { + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +const PRODUCT_NAME = '"KitchenSinktablet"'; -var PRODUCT_NAME = '"KitchenSinktablet"'; +describe('addAndRemoveToFromLibrarySearchPaths', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.addAndRemoveToFromLibrarySearchPaths = { - 'add should add the path to each configuration section':function(test) { + it('add should add the path to each configuration section', () => { proj.addToLibrarySearchPaths({ - path:'some/path/poop.a' + path: 'some/path/poop.a' }); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.LIBRARY_SEARCH_PATHS; - test.ok(lib[1].indexOf('$(SRCROOT)/KitchenSinktablet/some/path') > -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.LIBRARY_SEARCH_PATHS; + assert.ok(lib[1].indexOf('$(SRCROOT)/KitchenSinktablet/some/path') > -1); } - test.done(); - }, - 'add should not mangle string arguments and add to each config section':function(test) { - var libPath = '../../some/path'; + }); + it('add should not mangle string arguments and add to each config section', () => { + const libPath = '../../some/path'; proj.addToLibrarySearchPaths(libPath); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.LIBRARY_SEARCH_PATHS; - test.ok(lib[1].indexOf(libPath) > -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.LIBRARY_SEARCH_PATHS; + assert.ok(lib[1].indexOf(libPath) > -1); } - test.done(); - }, - 'remove should remove from the path to each configuration section':function(test) { - var libPath = 'some/path/poop.a'; + }); + it('remove should remove from the path to each configuration section', () => { + const libPath = 'some/path/poop.a'; proj.addToLibrarySearchPaths({ - path:libPath + path: libPath }); proj.removeFromLibrarySearchPaths({ - path:libPath + path: libPath }); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.LIBRARY_SEARCH_PATHS; - test.ok(lib.length === 1); - test.ok(lib[0].indexOf('$(SRCROOT)/KitchenSinktablet/some/path') == -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.LIBRARY_SEARCH_PATHS; + assert.ok(lib.length === 1); + assert.ok(lib[0].indexOf('$(SRCROOT)/KitchenSinktablet/some/path') === -1); } - test.done(); - } -} + }); +}); diff --git a/test/OtherLinkerFlags.js b/test/OtherLinkerFlags.js index de59f4c0..1adced36 100644 --- a/test/OtherLinkerFlags.js +++ b/test/OtherLinkerFlags.js @@ -1,60 +1,60 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); + http://www.apache.org/licenses/LICENSE-2.0 -function cleanHash() { + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +const PRODUCT_NAME = '"KitchenSinktablet"'; -var PRODUCT_NAME = '"KitchenSinktablet"'; +describe('addAndRemoveToFromOtherLinkerFlags', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.addAndRemoveToFromOtherLinkerFlags = { - 'add should add the flag to each configuration section':function(test) { - var flag = 'some/flag'; + it('add should add the flag to each configuration section', () => { + const flag = 'some/flag'; proj.addToOtherLinkerFlags(flag); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.OTHER_LDFLAGS; - test.ok(lib[1].indexOf(flag) > -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.OTHER_LDFLAGS; + assert.ok(lib[1].indexOf(flag) > -1); } - test.done(); - }, - 'remove should remove from the path to each configuration section':function(test) { - var flag = 'some/flag'; + }); + it('remove should remove from the path to each configuration section', () => { + const flag = 'some/flag'; proj.addToOtherLinkerFlags(flag); proj.removeFromOtherLinkerFlags(flag); - var config = proj.pbxXCBuildConfigurationSection(); - for (var ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; - var lib = config[ref].buildSettings.OTHER_LDFLAGS; - test.ok(lib.length === 1); - test.ok(lib[0].indexOf(flag) == -1); + const config = proj.pbxXCBuildConfigurationSection(); + for (const ref in config) { + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; + const lib = config[ref].buildSettings.OTHER_LDFLAGS; + assert.ok(lib.length === 1); + assert.ok(lib[0].indexOf(flag) === -1); } - test.done(); - } -} + }); +}); diff --git a/test/addBuildPhase.js b/test/addBuildPhase.js index eb105f80..2711a43e 100644 --- a/test/addBuildPhase.js +++ b/test/addBuildPhase.js @@ -1,197 +1,240 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addBuildPhase = { - 'should return a pbxBuildPhase': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXSourcesBuildPhase', 'My build phase'); - - test.ok(typeof buildPhase === 'object'); - test.done() - }, - 'should set a uuid on the pbxBuildPhase': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXSourcesBuildPhase', 'My build phase'); - - test.ok(buildPhase.uuid); - test.done() - }, - 'should add all files to build phase': function (test) { - var buildPhase = proj.addBuildPhase(['file.m', 'assets.bundle'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase; - for (var index = 0; index < buildPhase.files.length; index++) { - var file = buildPhase.files[index]; - test.ok(file.value); +describe('addBuildPhase', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxBuildPhase', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXSourcesBuildPhase', 'My build phase'); + assert.ok(typeof buildPhase === 'object'); + }); + + it('should set a uuid on the pbxBuildPhase', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXSourcesBuildPhase', 'My build phase'); + assert.ok(buildPhase.uuid); + }); + + it('should add all files to build phase', () => { + const buildPhase = proj.addBuildPhase(['file.m', 'assets.bundle'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase; + for (let index = 0; index < buildPhase.files.length; index++) { + const file = buildPhase.files[index]; + assert.ok(file.value); } + }); - test.done() - }, - 'should add the PBXBuildPhase object correctly': function (test) { - var buildPhase = proj.addBuildPhase(['file.m', 'assets.bundle'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase, - buildPhaseInPbx = proj.buildPhaseObject('PBXResourcesBuildPhase', 'My build phase'); - - test.equal(buildPhaseInPbx, buildPhase); - test.equal(buildPhaseInPbx.isa, 'PBXResourcesBuildPhase'); - test.equal(buildPhaseInPbx.buildActionMask, 2147483647); - test.equal(buildPhaseInPbx.runOnlyForDeploymentPostprocessing, 0); - test.done(); - }, - 'should add each of the files to PBXBuildFile section': function (test) { - var buildPhase = proj.addBuildPhase(['file.m', 'assets.bundle'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase, - buildFileSection = proj.pbxBuildFileSection(); - - for (var index = 0; index < buildPhase.files.length; index++) { - var file = buildPhase.files[index]; - test.ok(buildFileSection[file.value]); - } + it('should add the PBXBuildPhase object correctly', () => { + const buildPhase = proj.addBuildPhase(['file.m', 'assets.bundle'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase; + const buildPhaseInPbx = proj.buildPhaseObject('PBXResourcesBuildPhase', 'My build phase'); - test.done(); - }, - 'should add each of the files to PBXFileReference section': function (test) { - var buildPhase = proj.addBuildPhase(['file.m', 'assets.bundle'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase, - fileRefSection = proj.pbxFileReferenceSection(), - buildFileSection = proj.pbxBuildFileSection(), - fileRefs = []; + assert.equal(buildPhaseInPbx, buildPhase); + assert.equal(buildPhaseInPbx.isa, 'PBXResourcesBuildPhase'); + assert.equal(buildPhaseInPbx.buildActionMask, 2147483647); + assert.equal(buildPhaseInPbx.runOnlyForDeploymentPostprocessing, 0); + }); - for (var index = 0; index < buildPhase.files.length; index++) { - var file = buildPhase.files[index], - fileRef = buildFileSection[file.value].fileRef; + it('should add each of the files to PBXBuildFile section', () => { + const buildPhase = proj.addBuildPhase(['file.m', 'assets.bundle'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase; + const buildFileSection = proj.pbxBuildFileSection(); - test.ok(fileRefSection[fileRef]); + for (let index = 0; index < buildPhase.files.length; index++) { + const file = buildPhase.files[index]; + assert.ok(buildFileSection[file.value]); } + }); + + it('should add each of the files to PBXFileReference section', () => { + const buildPhase = proj.addBuildPhase(['file.m', 'assets.bundle'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase; + const fileRefSection = proj.pbxFileReferenceSection(); + const buildFileSection = proj.pbxBuildFileSection(); - test.done(); - }, - 'should not add files to PBXFileReference section if already added': function (test) { - var fileRefSection = proj.pbxFileReferenceSection(), - initialFileReferenceSectionItemsCount = Object.keys(fileRefSection), - buildPhase = proj.addBuildPhase(['AppDelegate.m', 'main.m'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase, - afterAdditionBuildFileSectionItemsCount = Object.keys(fileRefSection); - - test.deepEqual(initialFileReferenceSectionItemsCount, afterAdditionBuildFileSectionItemsCount); - test.done(); - }, - 'should not add files to PBXBuildFile section if already added': function (test) { - var buildFileSection = proj.pbxBuildFileSection(), - initialBuildFileSectionItemsCount = Object.keys(buildFileSection), - buildPhase = proj.addBuildPhase(['AppDelegate.m', 'main.m'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase, - afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); - - test.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); - test.done(); - }, - 'should add only missing files to PBXFileReference section': function (test) { - var fileRefSection = proj.pbxFileReferenceSection(), - buildFileSection = proj.pbxBuildFileSection(), - initialFileReferenceSectionItemsCount = Object.keys(fileRefSection), - buildPhase = proj.addBuildPhase(['file.m', 'AppDelegate.m'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase, - afterAdditionBuildFileSectionItemsCount = Object.keys(fileRefSection); - - for (var index = 0; index < buildPhase.files.length; index++) { - var file = buildPhase.files[index], - fileRef = buildFileSection[file.value].fileRef; - - test.ok(fileRefSection[fileRef]); + for (let index = 0; index < buildPhase.files.length; index++) { + const file = buildPhase.files[index]; + const fileRef = buildFileSection[file.value].fileRef; + + assert.ok(fileRefSection[fileRef]); + } + }); + + it('should not add files to PBXFileReference section if already added', () => { + const fileRefSection = proj.pbxFileReferenceSection(); + const initialFileReferenceSectionItemsCount = Object.keys(fileRefSection); + proj.addBuildPhase(['AppDelegate.m', 'main.m'], 'PBXResourcesBuildPhase', 'My build phase'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(fileRefSection); + + assert.deepEqual(initialFileReferenceSectionItemsCount, afterAdditionBuildFileSectionItemsCount); + }); + + it('should not add files to PBXBuildFile section if already added', () => { + const buildFileSection = proj.pbxBuildFileSection(); + const initialBuildFileSectionItemsCount = Object.keys(buildFileSection); + proj.addBuildPhase(['AppDelegate.m', 'main.m'], 'PBXResourcesBuildPhase', 'My build phase'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); + + assert.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); + }); + + it('should add only missing files to PBXFileReference section', () => { + const fileRefSection = proj.pbxFileReferenceSection(); + const buildFileSection = proj.pbxBuildFileSection(); + const initialFileReferenceSectionItemsCount = Object.keys(fileRefSection); + const buildPhase = proj.addBuildPhase(['file.m', 'AppDelegate.m'], 'PBXResourcesBuildPhase', 'My build phase').buildPhase; + const afterAdditionBuildFileSectionItemsCount = Object.keys(fileRefSection); + + for (let index = 0; index < buildPhase.files.length; index++) { + const file = buildPhase.files[index]; + const fileRef = buildFileSection[file.value].fileRef; + + assert.ok(fileRefSection[fileRef]); } - test.deepEqual(initialFileReferenceSectionItemsCount.length, afterAdditionBuildFileSectionItemsCount.length - 2); - test.done(); - }, - 'should set target to Wrapper given \'application\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'application').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 1); - test.done(); - }, - 'should set target to Plugins given \'app_extension\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'app_extension').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 13); - test.done(); - }, - 'should set target to Wapper given \'bundle\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'bundle').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 1); - test.done(); - }, - 'should set target to Wapper given \'command_line_tool\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'command_line_tool').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 1); - test.done(); - }, - 'should set target to Products Directory given \'dynamic_library\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'dynamic_library').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 16); - test.done(); - }, - 'should set target to Shared Framework given \'framework\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'framework').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 11); - test.done(); - }, - 'should set target to Frameworks given \'frameworks\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'frameworks').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 10); - test.done(); - }, - 'should set target to Products Directory given \'static_library\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'static_library').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 16); - test.done(); - }, - 'should set target to Wrapper given \'unit_test_bundle\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'unit_test_bundle').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 1); - test.done(); - }, - 'should set target to Wrapper given \'watch_app\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'watch_app').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 1); - test.done(); - }, - 'should set target to Products Directory given \'watch2_app\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'watch2_app').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 16); - test.done(); - }, - 'should set target to Plugins given \'watch_extension\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'watch_extension').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 13); - test.done(); - }, - 'should set target to Plugins given \'watch2_extension\' as target': function (test) { - var buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'watch2_extension').buildPhase; - test.equal(buildPhase.dstSubfolderSpec, 13); - test.done(); - }, - 'should add a script build phase to echo "hello world!"': function(test) { - var options = {shellPath: '/bin/sh', shellScript: 'echo "hello world!"'}; - var buildPhase = proj.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Run a script', proj.getFirstTarget().uuid, options).buildPhase; - test.equal(buildPhase.shellPath, '/bin/sh'); - test.equal(buildPhase.shellScript, '"echo \\"hello world!\\""'); - test.done(); - }, -} + assert.deepEqual(initialFileReferenceSectionItemsCount.length, afterAdditionBuildFileSectionItemsCount.length - 2); + }); + + it('should set target to Wrapper given \'application\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'application').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 1); + }); + + it('should set target to Plugins given \'app_extension\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'app_extension').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 13); + }); + + it('should set target to Wapper given \'bundle\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'bundle').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 1); + }); + + it('should set target to Wapper given \'command_line_tool\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'command_line_tool').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 1); + }); + + it('should set target to Products Directory given \'dynamic_library\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'dynamic_library').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 16); + }); + + it('should set target to Shared Framework given \'framework\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'framework').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 11); + }); + + it('should set target to Frameworks given \'frameworks\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'frameworks').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 10); + }); + + it('should set target to Products Directory given \'static_library\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'static_library').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 16); + }); + + it('should set target to Wrapper given \'unit_test_bundle\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'unit_test_bundle').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 1); + }); + + it('should set target to Wrapper given \'watch_app\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'watch_app').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 1); + }); + + it('should set target to Products Directory given \'watch2_app\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'watch2_app').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 16); + }); + + it('should set target to Plugins given \'watch_extension\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'watch_extension').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 13); + }); + + it('should set target to Plugins given \'watch2_extension\' as target', () => { + const buildPhase = proj.addBuildPhase(['file.m'], 'PBXCopyFilesBuildPhase', 'Copy Files', proj.getFirstTarget().uuid, 'watch2_extension').buildPhase; + assert.equal(buildPhase.dstSubfolderSpec, 13); + }); + + it('should add a script build phase to echo "hello world!"', () => { + const options = { shellPath: '/bin/sh', shellScript: 'echo "hello world!"' }; + const buildPhase = proj.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Run a script', proj.getFirstTarget().uuid, options).buildPhase; + assert.equal(buildPhase.shellPath, '/bin/sh'); + assert.equal(buildPhase.shellScript, '"echo \\"hello world!\\""'); + }); + + it('should add runOnlyForDeploymentPostprocessing option to run scripts', () => { + const options = { shellPath: '/bin/sh', shellScript: 'echo "hello world!"', runOnlyForDeploymentPostprocessing: 1 }; + const buildPhase = proj.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Run a script', proj.getFirstTarget().uuid, options).buildPhase; + assert.equal(buildPhase.runOnlyForDeploymentPostprocessing, 1); + }); + + it('should add the PBXBuildPhase with alwaysOutOfDate property', () => { + const options = { + shellPath: '/bin/sh', + shellScript: 'test', + alwaysOutOfDate: true + }; + + const buildPhase = proj.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Run a script', proj.getFirstTarget().uuid, options).buildPhase; + assert.equal(buildPhase.shellPath, '/bin/sh'); + assert.equal(buildPhase.shellScript, '"test"'); + assert.strictEqual(buildPhase.alwaysOutOfDate, 1); + }); + + it('should add the PBXBuildPhase without alwaysOutOfDate property', () => { + const options = { shellPath: '/bin/sh', shellScript: 'test' }; + + const buildPhase = proj.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Run a script', proj.getFirstTarget().uuid, options).buildPhase; + assert.equal(buildPhase.shellPath, '/bin/sh'); + assert.equal(buildPhase.shellScript, '"test"'); + assert.strictEqual(buildPhase.alwaysOutOfDate, undefined); + }); + + it('should not throw error when a non-restricted value is used for build phase type.', () => { + assert.doesNotThrow( + () => { + proj.addBuildPhase(['MyAssets.xcassets'], 'FooBar', 'Resources'); + }, + /Error: "FooBar" is restricted and cannot be used as a build phase type\./ + ); + }); + + it('should throw error when a restricted value was passed in for a build phase type.', () => { + assert.throws( + () => { + proj.addBuildPhase(['MyAssets.xcassets'], 'prototype', 'Resources'); + }, + /Error: "prototype" is restricted and cannot be used as a build phase type\./ + ); + }); +}); diff --git a/test/addFramework.js b/test/addFramework.js index c3c32009..c43a7176 100644 --- a/test/addFramework.js +++ b/test/addFramework.js @@ -1,40 +1,40 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -function nonComments(obj) { - var keys = Object.keys(obj), - newObj = {}, i = 0; +function nonComments (obj) { + const keys = Object.keys(obj); + const newObj = {}; - for (i; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { if (!/_comment$/.test(keys[i])) { newObj[keys[i]] = obj[keys[i]]; } @@ -43,210 +43,199 @@ function nonComments(obj) { return newObj; } -function frameworkSearchPaths(proj) { - var configs = nonComments(proj.pbxXCBuildConfigurationSection()), - allPaths = [], - ids = Object.keys(configs), i, buildSettings; +function frameworkSearchPaths (proj) { + const configs = nonComments(proj.pbxXCBuildConfigurationSection()); + const allPaths = []; + const ids = Object.keys(configs); + let buildSettings; - for (i = 0; i< ids.length; i++) { + for (let i = 0; i < ids.length; i++) { buildSettings = configs[ids[i]].buildSettings; - if (buildSettings['FRAMEWORK_SEARCH_PATHS']) { - allPaths.push(buildSettings['FRAMEWORK_SEARCH_PATHS']); + if (buildSettings.FRAMEWORK_SEARCH_PATHS) { + allPaths.push(buildSettings.FRAMEWORK_SEARCH_PATHS); } } return allPaths; } -exports.addFramework = { - 'should return a pbxFile': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'); - - test.equal(newFile.constructor, pbxFile); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'); - - test.ok(newFile.fileRef); - test.done() - }, - 'should populate the PBXFileReference section with 2 fields': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'); - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(68, frsLength); - test.ok(fileRefSection[newFile.fileRef]); - test.ok(fileRefSection[newFile.fileRef + '_comment']); - - test.done(); - }, - 'should populate the PBXFileReference comment correctly': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'); - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = newFile.fileRef + '_comment'; - - test.equal(fileRefSection[commentKey], 'libsqlite3.dylib'); - test.done(); - }, - 'should add the PBXFileReference object correctly': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; - - test.equal(fileRefEntry.isa, 'PBXFileReference'); - test.equal(fileRefEntry.lastKnownFileType, 'compiled.mach-o.dylib'); - test.equal(fileRefEntry.name, '"libsqlite3.dylib"'); - test.equal(fileRefEntry.path, '"usr/lib/libsqlite3.dylib"'); - test.equal(fileRefEntry.sourceTree, 'SDKROOT'); - - test.done(); - }, - 'should populate the PBXBuildFile section with 2 fields': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; - - test.equal(60, bfsLength); - test.ok(buildFileSection[newFile.uuid]); - test.ok(buildFileSection[newFile.uuid + '_comment']); - - test.done(); - }, - 'should add the PBXBuildFile comment correctly': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - commentKey = newFile.uuid + '_comment', - buildFileSection = proj.pbxBuildFileSection(); - - test.equal(buildFileSection[commentKey], 'libsqlite3.dylib in Frameworks'); - test.done(); - }, - 'should add the PBXBuildFile object correctly': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[newFile.uuid]; - - test.equal(buildFileEntry.isa, 'PBXBuildFile'); - test.equal(buildFileEntry.fileRef, newFile.fileRef); - test.equal(buildFileEntry.fileRef_comment, 'libsqlite3.dylib'); - test.equal(buildFileEntry.settings, undefined); - - test.done(); - }, - 'should add the PBXBuildFile object correctly /w weak linked frameworks': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib', { weak: true }), - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[newFile.uuid]; - - test.equal(buildFileEntry.isa, 'PBXBuildFile'); - test.equal(buildFileEntry.fileRef, newFile.fileRef); - test.equal(buildFileEntry.fileRef_comment, 'libsqlite3.dylib'); - test.deepEqual(buildFileEntry.settings, { ATTRIBUTES: [ 'Weak' ] }); - - test.done(); - }, - 'should add to the Frameworks PBXGroup': function (test) { - var newLength = proj.pbxGroupByName('Frameworks').children.length + 1, - newFile = proj.addFramework('libsqlite3.dylib'), - frameworks = proj.pbxGroupByName('Frameworks'); - - test.equal(frameworks.children.length, newLength); - test.done(); - }, - 'should have the right values for the PBXGroup entry': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - frameworks = proj.pbxGroupByName('Frameworks').children, - framework = frameworks[frameworks.length - 1]; - - test.equal(framework.comment, 'libsqlite3.dylib'); - test.equal(framework.value, newFile.fileRef); - test.done(); - }, - 'should add to the PBXFrameworksBuildPhase': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - frameworks = proj.pbxFrameworksBuildPhaseObj(); - - test.equal(frameworks.files.length, 16); - test.done(); - }, - 'should not add to the PBXFrameworksBuildPhase': function (test) { - var newFile = proj.addFramework('Private.framework', {link: false}), - frameworks = proj.pbxFrameworksBuildPhaseObj(); - - test.equal(frameworks.files.length, 15); - test.done(); - }, - 'should have the right values for the Sources entry': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - frameworks = proj.pbxFrameworksBuildPhaseObj(), - framework = frameworks.files[15]; - - test.equal(framework.comment, 'libsqlite3.dylib in Frameworks'); - test.equal(framework.value, newFile.uuid); - test.done(); - }, - 'duplicate entries': { - 'should return false': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'); - - test.ok(!proj.addFramework('libsqlite3.dylib')); - test.done(); - } - }, - 'should pbxFile correctly for custom frameworks': function (test) { - var newFile = proj.addFramework('/path/to/Custom.framework', {customFramework: true}); - - test.ok(newFile.customFramework); - test.ok(!newFile.fileEncoding); - test.equal(newFile.sourceTree, '""'); - test.equal(newFile.group, 'Frameworks'); - test.equal(newFile.basename, 'Custom.framework'); - test.equal(newFile.dirname, '/path/to'); +describe('addFramework', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxFile', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + assert.equal(newFile.constructor, PBXFile); + }); + + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + assert.ok(newFile.fileRef); + }); + + it('should populate the PBXFileReference section with 2 fields', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + + assert.equal(68, frsLength); + assert.ok(fileRefSection[newFile.fileRef]); + assert.ok(fileRefSection[newFile.fileRef + '_comment']); + }); + + it('should populate the PBXFileReference comment correctly', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const fileRefSection = proj.pbxFileReferenceSection(); + const commentKey = newFile.fileRef + '_comment'; + + assert.equal(fileRefSection[commentKey], 'libsqlite3.dylib'); + }); + + it('should add the PBXFileReference object correctly', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const fileRefSection = proj.pbxFileReferenceSection(); + const fileRefEntry = fileRefSection[newFile.fileRef]; + + assert.equal(fileRefEntry.isa, 'PBXFileReference'); + assert.equal(fileRefEntry.lastKnownFileType, 'compiled.mach-o.dylib'); + assert.equal(fileRefEntry.name, '"libsqlite3.dylib"'); + assert.equal(fileRefEntry.path, '"usr/lib/libsqlite3.dylib"'); + assert.equal(fileRefEntry.sourceTree, 'SDKROOT'); + }); + + it('should populate the PBXBuildFile section with 2 fields', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; + + assert.equal(60, bfsLength); + assert.ok(buildFileSection[newFile.uuid]); + assert.ok(buildFileSection[newFile.uuid + '_comment']); + }); + + it('should add the PBXBuildFile comment correctly', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const commentKey = newFile.uuid + '_comment'; + const buildFileSection = proj.pbxBuildFileSection(); + + assert.equal(buildFileSection[commentKey], 'libsqlite3.dylib in Frameworks'); + }); + + it('should add the PBXBuildFile object correctly', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const buildFileSection = proj.pbxBuildFileSection(); + const buildFileEntry = buildFileSection[newFile.uuid]; + + assert.equal(buildFileEntry.isa, 'PBXBuildFile'); + assert.equal(buildFileEntry.fileRef, newFile.fileRef); + assert.equal(buildFileEntry.fileRef_comment, 'libsqlite3.dylib'); + assert.equal(buildFileEntry.settings, undefined); + }); + + it('should add the PBXBuildFile object correctly /w weak linked frameworks', () => { + const newFile = proj.addFramework('libsqlite3.dylib', { weak: true }); + const buildFileSection = proj.pbxBuildFileSection(); + const buildFileEntry = buildFileSection[newFile.uuid]; + + assert.equal(buildFileEntry.isa, 'PBXBuildFile'); + assert.equal(buildFileEntry.fileRef, newFile.fileRef); + assert.equal(buildFileEntry.fileRef_comment, 'libsqlite3.dylib'); + assert.deepEqual(buildFileEntry.settings, { ATTRIBUTES: ['Weak'] }); + }); + + it('should add to the Frameworks PBXGroup', () => { + const newLength = proj.pbxGroupByName('Frameworks').children.length + 1; + proj.addFramework('libsqlite3.dylib'); + const frameworks = proj.pbxGroupByName('Frameworks'); + + assert.equal(frameworks.children.length, newLength); + }); + + it('should have the right values for the PBXGroup entry', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const frameworks = proj.pbxGroupByName('Frameworks').children; + const framework = frameworks[frameworks.length - 1]; + + assert.equal(framework.comment, 'libsqlite3.dylib'); + assert.equal(framework.value, newFile.fileRef); + }); + + it('should add to the PBXFrameworksBuildPhase', () => { + proj.addFramework('libsqlite3.dylib'); + const frameworks = proj.pbxFrameworksBuildPhaseObj(); + assert.equal(frameworks.files.length, 16); + }); + + it('should not add to the PBXFrameworksBuildPhase', () => { + proj.addFramework('Private.framework', { link: false }); + const frameworks = proj.pbxFrameworksBuildPhaseObj(); + + assert.equal(frameworks.files.length, 15); + }); + + it('should have the right values for the Sources entry', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const frameworks = proj.pbxFrameworksBuildPhaseObj(); + const framework = frameworks.files[15]; + + assert.equal(framework.comment, 'libsqlite3.dylib in Frameworks'); + assert.equal(framework.value, newFile.uuid); + }); + + it('should return false', () => { + proj.addFramework('libsqlite3.dylib'); + assert.ok(!proj.addFramework('libsqlite3.dylib')); + }); + + it('should pbxFile correctly for custom frameworks', () => { + const newFile = proj.addFramework('/path/to/Custom.framework', { customFramework: true }); + + assert.ok(newFile.customFramework); + assert.ok(!newFile.fileEncoding); + assert.equal(newFile.sourceTree, '""'); + assert.equal(newFile.group, 'Frameworks'); + assert.equal(newFile.basename, 'Custom.framework'); + assert.equal(newFile.dirname, '/path/to'); // XXX framework has to be copied over to PROJECT root. That is what XCode does when you drag&drop - test.equal(newFile.path, '/path/to/Custom.framework'); - + assert.equal(newFile.path, '/path/to/Custom.framework'); // should add path to framework search path - var frameworkPaths = frameworkSearchPaths(proj); - expectedPath = '"\\"/path/to\\""'; + const frameworkPaths = frameworkSearchPaths(proj); + const expectedPath = '"\\"/path/to\\""'; - for (i = 0; i < frameworkPaths.length; i++) { - var current = frameworkPaths[i]; - test.ok(current.indexOf('"$(inherited)"') >= 0); - test.ok(current.indexOf(expectedPath) >= 0); + for (let i = 0; i < frameworkPaths.length; i++) { + const current = frameworkPaths[i]; + assert.ok(current.indexOf('"$(inherited)"') >= 0); + assert.ok(current.indexOf(expectedPath) >= 0); } - test.done(); - }, - 'should add to the Embed Frameworks PBXCopyFilesBuildPhase': function (test) { - var newFile = proj.addFramework('/path/to/SomeEmbeddableCustom.framework', {customFramework: true, embed: true}), - frameworks = proj.pbxEmbedFrameworksBuildPhaseObj(); - - var buildPhaseInPbx = proj.pbxEmbedFrameworksBuildPhaseObj(); - test.equal(buildPhaseInPbx.dstSubfolderSpec, 10); - - test.equal(frameworks.files.length, 1); - test.done(); - }, - 'should not add to the Embed Frameworks PBXCopyFilesBuildPhase by default': function (test) { - var newFile = proj.addFramework('/path/to/Custom.framework', {customFramework: true}), - frameworks = proj.pbxEmbedFrameworksBuildPhaseObj(); - - test.equal(frameworks.files.length, 0); - test.done(); - }, - 'should add the PBXBuildFile object correctly /w signable frameworks': function (test) { - var newFile = proj.addFramework('/path/to/SomeSignable.framework', { customFramework: true, embed: true, sign: true }), - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[newFile.uuid]; - - test.equal(newFile.group, 'Embed Frameworks'); - test.equal(buildFileEntry.isa, 'PBXBuildFile'); - test.equal(buildFileEntry.fileRef, newFile.fileRef); - test.equal(buildFileEntry.fileRef_comment, 'SomeSignable.framework'); - test.deepEqual(buildFileEntry.settings, { ATTRIBUTES: [ 'CodeSignOnCopy' ] }); - - test.done(); - }, -} + }); + + it('should add to the Embed Frameworks PBXCopyFilesBuildPhase', () => { + proj.addFramework('/path/to/SomeEmbeddableCustom.framework', { customFramework: true, embed: true }); + const frameworks = proj.pbxEmbedFrameworksBuildPhaseObj(); + const buildPhaseInPbx = proj.pbxEmbedFrameworksBuildPhaseObj(); + assert.equal(buildPhaseInPbx.dstSubfolderSpec, 10); + + assert.equal(frameworks.files.length, 1); + }); + + it('should not add to the Embed Frameworks PBXCopyFilesBuildPhase by default', () => { + proj.addFramework('/path/to/Custom.framework', { customFramework: true }); + const frameworks = proj.pbxEmbedFrameworksBuildPhaseObj(); + assert.equal(frameworks.files.length, 0); + }); + + it('should add the PBXBuildFile object correctly /w signable frameworks', () => { + const newFile = proj.addFramework('/path/to/SomeSignable.framework', { customFramework: true, embed: true, sign: true }); + const buildFileSection = proj.pbxBuildFileSection(); + const buildFileEntry = buildFileSection[newFile.uuid]; + + assert.equal(newFile.group, 'Embed Frameworks'); + assert.equal(buildFileEntry.isa, 'PBXBuildFile'); + assert.equal(buildFileEntry.fileRef, newFile.fileRef); + assert.equal(buildFileEntry.fileRef_comment, 'SomeSignable.framework'); + assert.deepEqual(buildFileEntry.settings, { ATTRIBUTES: ['CodeSignOnCopy'] }); + }); +}); diff --git a/test/addHeaderFile.js b/test/addHeaderFile.js index f9bd71a2..cc8e621e 100644 --- a/test/addHeaderFile.js +++ b/test/addHeaderFile.js @@ -1,115 +1,113 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addHeaderFile = { - 'should return a pbxFile': function (test) { - var newFile = proj.addHeaderFile('file.h'); - - test.equal(newFile.constructor, pbxFile); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addHeaderFile('file.h'); - - test.ok(newFile.fileRef); - test.done() - }, - 'should populate the PBXFileReference section with 2 fields': function (test) { - var newFile = proj.addHeaderFile('file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(68, frsLength); - test.ok(fileRefSection[newFile.fileRef]); - test.ok(fileRefSection[newFile.fileRef + '_comment']); - - test.done(); - }, - 'should populate the PBXFileReference comment correctly': function (test) { - var newFile = proj.addHeaderFile('file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = newFile.fileRef + '_comment'; - - test.equal(fileRefSection[commentKey], 'file.h'); - test.done(); - }, - 'should add the PBXFileReference object correctly': function (test) { - var newFile = proj.addHeaderFile('Plugins/file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; - - test.equal(fileRefEntry.isa, 'PBXFileReference'); - test.equal(fileRefEntry.fileEncoding, 4); - test.equal(fileRefEntry.lastKnownFileType, 'sourcecode.c.h'); - test.equal(fileRefEntry.name, '"file.h"'); - test.equal(fileRefEntry.path, '"file.h"'); - test.equal(fileRefEntry.sourceTree, '""'); - - test.done(); - }, - 'should add to the Plugins PBXGroup group': function (test) { - var newFile = proj.addHeaderFile('Plugins/file.h'), - plugins = proj.pbxGroupByName('Plugins'); - - test.equal(plugins.children.length, 1); - test.done(); - }, - 'should have the right values for the PBXGroup entry': function (test) { - var newFile = proj.addHeaderFile('Plugins/file.h'), - plugins = proj.pbxGroupByName('Plugins'), - pluginObj = plugins.children[0]; - - test.equal(pluginObj.comment, 'file.h'); - test.equal(pluginObj.value, newFile.fileRef); - test.done(); - }, - 'duplicate entries': { - 'should return false': function (test) { - var newFile = proj.addHeaderFile('Plugins/file.h'); - - test.ok(!proj.addHeaderFile('Plugins/file.h')); - test.done(); - }, - 'should not add another entry anywhere': function (test) { - var newFile = proj.addHeaderFile('Plugins/file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length, - plugins = proj.pbxGroupByName('Plugins'); - - proj.addHeaderFile('Plugins/file.h'); - - test.equal(68, frsLength); - test.equal(plugins.children.length, 1); - test.done(); - } - } -} +describe('addHeaderFile', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxFile', () => { + const newFile = proj.addHeaderFile('file.h'); + assert.equal(newFile.constructor, PBXFile); + }); + + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addHeaderFile('file.h'); + assert.ok(newFile.fileRef); + }); + + it('should populate the PBXFileReference section with 2 fields', () => { + const newFile = proj.addHeaderFile('file.h'); + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + + assert.equal(68, frsLength); + assert.ok(fileRefSection[newFile.fileRef]); + assert.ok(fileRefSection[newFile.fileRef + '_comment']); + }); + + it('should populate the PBXFileReference comment correctly', () => { + const newFile = proj.addHeaderFile('file.h'); + const fileRefSection = proj.pbxFileReferenceSection(); + const commentKey = newFile.fileRef + '_comment'; + + assert.equal(fileRefSection[commentKey], 'file.h'); + }); + + it('should add the PBXFileReference object correctly', () => { + const newFile = proj.addHeaderFile('Plugins/file.h'); + const fileRefSection = proj.pbxFileReferenceSection(); + const fileRefEntry = fileRefSection[newFile.fileRef]; + + assert.equal(fileRefEntry.isa, 'PBXFileReference'); + assert.equal(fileRefEntry.fileEncoding, 4); + assert.equal(fileRefEntry.lastKnownFileType, 'sourcecode.c.h'); + assert.equal(fileRefEntry.name, '"file.h"'); + assert.equal(fileRefEntry.path, '"file.h"'); + assert.equal(fileRefEntry.sourceTree, '""'); + }); + + it('should add to the Plugins PBXGroup group', () => { + proj.addHeaderFile('Plugins/file.h'); + + const plugins = proj.pbxGroupByName('Plugins'); + + assert.equal(plugins.children.length, 1); + }); + + it('should have the right values for the PBXGroup entry', () => { + const newFile = proj.addHeaderFile('Plugins/file.h'); + const plugins = proj.pbxGroupByName('Plugins'); + const pluginObj = plugins.children[0]; + + assert.equal(pluginObj.comment, 'file.h'); + assert.equal(pluginObj.value, newFile.fileRef); + }); + + it('addHeaderFile duplicate entries: should return false', () => { + proj.addHeaderFile('Plugins/file.h'); + assert.ok(!proj.addHeaderFile('Plugins/file.h')); + }); + + it('addHeaderFile duplicate entries: should not add another entry anywhere', () => { + proj.addHeaderFile('Plugins/file.h'); + + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + const plugins = proj.pbxGroupByName('Plugins'); + + proj.addHeaderFile('Plugins/file.h'); + + assert.equal(68, frsLength); + assert.equal(plugins.children.length, 1); + }); +}); diff --git a/test/addRemovePbxGroup.js b/test/addRemovePbxGroup.js index 8212f912..828e9775 100644 --- a/test/addRemovePbxGroup.js +++ b/test/addRemovePbxGroup.js @@ -1,177 +1,175 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('addRemovePbxGroup', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxGroup', () => { + const pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application', 'Application', '""'); + assert.ok(typeof pbxGroup === 'object'); + }); + + it('should set a uuid on the pbxGroup', () => { + const pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application', 'Application', '""'); + assert.ok(pbxGroup.uuid); + }); + + it('should add all files to pbxGroup', () => { + const pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application', 'Application', '""'); + for (let index = 0; index < pbxGroup.pbxGroup.children.length; index++) { + const file = pbxGroup.pbxGroup.children[index]; + assert.ok(file.value); + } + }); + + it('should add the PBXGroup object correctly', () => { + const pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application', '""'); + const pbxGroupInPbx = proj.pbxGroupByName('MyGroup'); + + assert.equal(pbxGroupInPbx.children, pbxGroup.pbxGroup.children); + assert.equal(pbxGroupInPbx.isa, 'PBXGroup'); + assert.equal(pbxGroupInPbx.path, 'Application'); + assert.equal(pbxGroupInPbx.sourceTree, '""'); + }); + + it('should add sourceTree if no other specified', () => { + proj.addPbxGroup(['file.m'], 'MyGroup', 'Application'); -exports.addRemovePbxGroup = { - 'should return a pbxGroup': function (test) { - var pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application', 'Application', '""'); - - test.ok(typeof pbxGroup === 'object'); - test.done() - }, - 'should set a uuid on the pbxGroup': function (test) { - var pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application', 'Application', '""'); - - test.ok(pbxGroup.uuid); - test.done() - }, - 'should add all files to pbxGroup': function (test) { - var pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application', 'Application', '""'); - for (var index = 0; index < pbxGroup.pbxGroup.children.length; index++) { - var file = pbxGroup.pbxGroup.children[index]; - test.ok(file.value); + const pbxGroupInPbx = proj.pbxGroupByName('MyGroup'); + + assert.equal(pbxGroupInPbx.sourceTree, '""'); + }); + + it('should add each of the files to PBXBuildFile section', () => { + const buildFileSection = proj.pbxBuildFileSection(); + for (const key in buildFileSection) { + assert.notEqual(buildFileSection[key].fileRef_comment, 'file.m'); + assert.notEqual(buildFileSection[key].fileRef_comment, 'assets.bundle'); } - test.done() - }, - 'should add the PBXGroup object correctly': function (test) { - var pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application', '""'); - pbxGroupInPbx = proj.pbxGroupByName('MyGroup'); - - test.equal(pbxGroupInPbx.children, pbxGroup.pbxGroup.children); - test.equal(pbxGroupInPbx.isa, 'PBXGroup'); - test.equal(pbxGroupInPbx.path, 'Application'); - test.equal(pbxGroupInPbx.sourceTree, '""'); - test.done(); - }, - 'should add sourceTree if no other specified': function (test) { - var pbxGroup = proj.addPbxGroup(['file.m'], 'MyGroup', 'Application'); - pbxGroupInPbx = proj.pbxGroupByName('MyGroup'); - - test.equal(pbxGroupInPbx.sourceTree, '""'); - test.done(); - }, - 'should add each of the files to PBXBuildFile section': function (test) { - var buildFileSection = proj.pbxBuildFileSection(); - for (var key in buildFileSection) { - test.notEqual(buildFileSection[key].fileRef_comment, 'file.m'); - test.notEqual(buildFileSection[key].fileRef_comment, 'assets.bundle'); + const initialBuildFileSectionItemsCount = Object.keys(buildFileSection); + proj.addPbxGroup(['file.m', 'assets.bundle'], 'MyGroup', 'Application', '""'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); + + assert.equal(initialBuildFileSectionItemsCount.length, afterAdditionBuildFileSectionItemsCount.length - 4); + }); + + it('should not add any of the files to PBXBuildFile section if already added', () => { + const buildFileSection = proj.pbxBuildFileSection(); + const initialBuildFileSectionItemsCount = Object.keys(buildFileSection); + proj.addPbxGroup(['AppDelegate.m', 'AppDelegate.h'], 'MyGroup', 'Application', '""'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); + + assert.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); + }); + + it('should not add any of the files to PBXBuildFile section when they contain special symbols and are already added', () => { + const buildFileSection = proj.pbxBuildFileSection(); + const initialBuildFileSectionItemsCount = Object.keys(buildFileSection); + proj.addPbxGroup(['KitchenSinktablet.app'], 'MyGroup', 'Application', '""'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); + + assert.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); + }); + + it('should add all files which are not added and not add files already added to PBXBuildFile section', () => { + const buildFileSection = proj.pbxBuildFileSection(); + for (const key in buildFileSection) { + assert.notEqual(buildFileSection[key].fileRef_comment, 'file.m'); + assert.notEqual(buildFileSection[key].fileRef_comment, 'assets.bundle'); } - var initialBuildFileSectionItemsCount = Object.keys(buildFileSection), - pbxGroup = proj.addPbxGroup(['file.m', 'assets.bundle'], 'MyGroup', 'Application', '""'), - afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); - - // for each file added in the build file section two keyes are added - one for the object and one for the comment - test.equal(initialBuildFileSectionItemsCount.length, afterAdditionBuildFileSectionItemsCount.length - 4); - test.done(); - }, - 'should not add any of the files to PBXBuildFile section if already added': function (test) { - var buildFileSection = proj.pbxBuildFileSection(), - initialBuildFileSectionItemsCount = Object.keys(buildFileSection), - pbxGroup = proj.addPbxGroup(['AppDelegate.m', 'AppDelegate.h'], 'MyGroup', 'Application', '""'), - afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); - - test.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); - test.done(); - }, - 'should not add any of the files to PBXBuildFile section when they contain special symbols and are already added': function (test) { - var buildFileSection = proj.pbxBuildFileSection(), - initialBuildFileSectionItemsCount = Object.keys(buildFileSection), - pbxGroup = proj.addPbxGroup(['KitchenSinktablet.app'], 'MyGroup', 'Application', '""'), - afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); - - test.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); - test.done(); - }, - 'should add all files which are not added and not add files already added to PBXBuildFile section': function (test) { - var buildFileSection = proj.pbxBuildFileSection(); - for (var key in buildFileSection) { - test.notEqual(buildFileSection[key].fileRef_comment, 'file.m'); - test.notEqual(buildFileSection[key].fileRef_comment, 'assets.bundle'); + const initialBuildFileSectionItemsCount = Object.keys(buildFileSection); + proj.addPbxGroup(['AppDelegate.m', 'AppDelegate.h', 'file.m', 'assets.bundle'], 'MyGroup', 'Application', '""'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); + + assert.equal(initialBuildFileSectionItemsCount.length, afterAdditionBuildFileSectionItemsCount.length - 4); + }); + + it('should add each of the files to PBXFileReference section', () => { + const fileReference = proj.pbxFileReferenceSection(); + for (const key in fileReference) { + assert.notEqual(fileReference[key].fileRef_comment, 'file.m'); + assert.notEqual(fileReference[key].fileRef_comment, 'assets.bundle'); } - var initialBuildFileSectionItemsCount = Object.keys(buildFileSection), - pbxGroup = proj.addPbxGroup(['AppDelegate.m', 'AppDelegate.h', 'file.m', 'assets.bundle'], 'MyGroup', 'Application', '""'), - afterAdditionBuildFileSectionItemsCount = Object.keys(buildFileSection); - - // for each file added in the build file section two keyes are added - one for the object and one for the comment - test.equal(initialBuildFileSectionItemsCount.length, afterAdditionBuildFileSectionItemsCount.length - 4); - test.done(); - }, - 'should add each of the files to PBXFileReference section': function (test) { - var fileReference = proj.pbxFileReferenceSection(); - for (var key in fileReference) { - test.notEqual(fileReference[key].fileRef_comment, 'file.m'); - test.notEqual(fileReference[key].fileRef_comment, 'assets.bundle'); + const pbxGroup = proj.addPbxGroup(['file.m', 'assets.bundle'], 'MyGroup', 'Application', '""'); + for (let index = 0; index < pbxGroup.pbxGroup.children.length; index++) { + const file = pbxGroup.pbxGroup.children[index]; + assert.ok(fileReference[file.value]); } - var pbxGroup = proj.addPbxGroup(['file.m', 'assets.bundle'], 'MyGroup', 'Application', '""'); - for (var index = 0; index < pbxGroup.pbxGroup.children.length; index++) { - var file = pbxGroup.pbxGroup.children[index]; - test.ok(fileReference[file.value]); + }); + + it('should not add any of the files to PBXFileReference section if already added', () => { + const fileReference = proj.pbxFileReferenceSection(); + const initialBuildFileSectionItemsCount = Object.keys(fileReference); + proj.addPbxGroup(['AppDelegate.m', 'AppDelegate.h'], 'MyGroup', 'Application', '""'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(fileReference); + + assert.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); + }); + + it('should not add any of the files to PBXFileReference section when they contain special symbols and are already added', () => { + const fileReference = proj.pbxFileReferenceSection(); + const initialBuildFileSectionItemsCount = Object.keys(fileReference); + proj.addPbxGroup(['KitchenSinktablet.app'], 'MyGroup', 'Application', '""'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(fileReference); + + assert.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); + }); + + it('should add all files which are not added and not add files already added to PBXFileReference section', () => { + const fileReference = proj.pbxFileReferenceSection(); + for (const key in fileReference) { + assert.notEqual(fileReference[key].fileRef_comment, 'file.m'); + assert.notEqual(fileReference[key].fileRef_comment, 'assets.bundle'); } - test.done(); - }, - 'should not add any of the files to PBXFileReference section if already added': function (test) { - var fileReference = proj.pbxFileReferenceSection (), - initialBuildFileSectionItemsCount = Object.keys(fileReference), - pbxGroup = proj.addPbxGroup(['AppDelegate.m', 'AppDelegate.h'], 'MyGroup', 'Application', '""'), - afterAdditionBuildFileSectionItemsCount = Object.keys(fileReference); - - test.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); - test.done(); - }, - 'should not add any of the files to PBXFileReference section when they contain special symbols and are already added': function (test) { - var fileReference = proj.pbxFileReferenceSection (), - initialBuildFileSectionItemsCount = Object.keys(fileReference), - pbxGroup = proj.addPbxGroup(['KitchenSinktablet.app'], 'MyGroup', 'Application', '""'), - afterAdditionBuildFileSectionItemsCount = Object.keys(fileReference); - - test.deepEqual(initialBuildFileSectionItemsCount, afterAdditionBuildFileSectionItemsCount); - test.done(); - }, - 'should add all files which are not added and not add files already added to PBXFileReference section': function (test) { - var fileReference = proj.pbxFileReferenceSection (); - for (var key in fileReference) { - test.notEqual(fileReference[key].fileRef_comment, 'file.m'); - test.notEqual(fileReference[key].fileRef_comment, 'assets.bundle'); - } + const initialBuildFileSectionItemsCount = Object.keys(fileReference); + proj.addPbxGroup(['AppDelegate.m', 'AppDelegate.h', 'file.m', 'assets.bundle'], 'MyGroup', 'Application', '""'); + const afterAdditionBuildFileSectionItemsCount = Object.keys(fileReference); - var initialBuildFileSectionItemsCount = Object.keys(fileReference), - pbxGroup = proj.addPbxGroup(['AppDelegate.m', 'AppDelegate.h', 'file.m', 'assets.bundle'], 'MyGroup', 'Application', '""'), - afterAdditionBuildFileSectionItemsCount = Object.keys(fileReference); + assert.equal(initialBuildFileSectionItemsCount.length, afterAdditionBuildFileSectionItemsCount.length - 4); + }); - // for each file added in the file reference section two keyes are added - one for the object and one for the comment - test.equal(initialBuildFileSectionItemsCount.length, afterAdditionBuildFileSectionItemsCount.length - 4); - test.done(); - }, - 'should remove a pbxGroup': function (test) { - var groupName = 'MyGroup'; + it('should remove a pbxGroup', () => { + const groupName = 'MyGroup'; proj.addPbxGroup(['file.m'], groupName, 'Application', 'Application', '""'); proj.removePbxGroup(groupName); - var pbxGroupInPbx = proj.pbxGroupByName(groupName); + const pbxGroupInPbx = proj.pbxGroupByName(groupName); console.log(pbxGroupInPbx); - test.ok(!pbxGroupInPbx); - test.done() - } -} + assert.ok(!pbxGroupInPbx); + }); +}); diff --git a/test/addResourceFile.js b/test/addResourceFile.js index 36afdb2c..fe5718a8 100644 --- a/test/addResourceFile.js +++ b/test/addResourceFile.js @@ -1,284 +1,286 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach, afterEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addResourceFile = { - 'should return a pbxFile': function (test) { - var newFile = proj.addResourceFile('assets.bundle'); - - test.equal(newFile.constructor, pbxFile); - test.done() - }, - 'should set a uuid on the pbxFile': function (test) { - var newFile = proj.addResourceFile('assets.bundle'); - - test.ok(newFile.uuid); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addResourceFile('assets.bundle'); - - test.ok(newFile.fileRef); - test.done() - }, - 'should populate the PBXBuildFile section with 2 fields': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; - - test.equal(60, bfsLength); - test.ok(buildFileSection[newFile.uuid]); - test.ok(buildFileSection[newFile.uuid + '_comment']); - - test.done(); - }, - 'should add the PBXBuildFile comment correctly': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - commentKey = newFile.uuid + '_comment', - buildFileSection = proj.pbxBuildFileSection(); - - test.equal(buildFileSection[commentKey], 'assets.bundle in Resources'); - test.done(); - }, - 'should add the PBXBuildFile object correctly': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[newFile.uuid]; - - test.equal(buildFileEntry.isa, 'PBXBuildFile'); - test.equal(buildFileEntry.fileRef, newFile.fileRef); - test.equal(buildFileEntry.fileRef_comment, 'assets.bundle'); - - test.done(); - }, - 'should populate the PBXFileReference section with 2 fields': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(68, frsLength); - test.ok(fileRefSection[newFile.fileRef]); - test.ok(fileRefSection[newFile.fileRef + '_comment']); - - test.done(); - }, - 'should populate the PBXFileReference comment correctly': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = newFile.fileRef + '_comment'; - - test.equal(fileRefSection[commentKey], 'assets.bundle'); - test.done(); - }, - 'should add the PBXFileReference object correctly': function (test) { +describe('addResourceFile', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxFile', () => { + const newFile = proj.addResourceFile('assets.bundle'); + assert.equal(newFile.constructor, PBXFile); + }); + + it('should set a uuid on the pbxFile', () => { + const newFile = proj.addResourceFile('assets.bundle'); + assert.ok(newFile.uuid); + }); + + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addResourceFile('assets.bundle'); + assert.ok(newFile.fileRef); + }); + + it('should populate the PBXBuildFile section with 2 fields', () => { + const newFile = proj.addResourceFile('assets.bundle'); + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; + + assert.equal(60, bfsLength); + assert.ok(buildFileSection[newFile.uuid]); + assert.ok(buildFileSection[newFile.uuid + '_comment']); + }); + + it('should add the PBXBuildFile comment correctly', () => { + const newFile = proj.addResourceFile('assets.bundle'); + const commentKey = newFile.uuid + '_comment'; + const buildFileSection = proj.pbxBuildFileSection(); + + assert.equal(buildFileSection[commentKey], 'assets.bundle in Resources'); + }); + + it('should add the PBXBuildFile object correctly', () => { + const newFile = proj.addResourceFile('assets.bundle'); + const buildFileSection = proj.pbxBuildFileSection(); + const buildFileEntry = buildFileSection[newFile.uuid]; + + assert.equal(buildFileEntry.isa, 'PBXBuildFile'); + assert.equal(buildFileEntry.fileRef, newFile.fileRef); + assert.equal(buildFileEntry.fileRef_comment, 'assets.bundle'); + }); + + it('should populate the PBXFileReference section with 2 fields', () => { + const newFile = proj.addResourceFile('assets.bundle'); + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + + assert.equal(68, frsLength); + assert.ok(fileRefSection[newFile.fileRef]); + assert.ok(fileRefSection[newFile.fileRef + '_comment']); + }); + + it('should populate the PBXFileReference comment correctly', () => { + const newFile = proj.addResourceFile('assets.bundle'); + const fileRefSection = proj.pbxFileReferenceSection(); + const commentKey = newFile.fileRef + '_comment'; + + assert.equal(fileRefSection[commentKey], 'assets.bundle'); + }); + + it('should add the PBXFileReference object correctly', () => { delete proj.pbxGroupByName('Resources').path; - var newFile = proj.addResourceFile('Resources/assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; - - test.equal(fileRefEntry.isa, 'PBXFileReference'); - test.equal(fileRefEntry.fileEncoding, undefined); - test.equal(fileRefEntry.lastKnownFileType, 'wrapper.plug-in'); - test.equal(fileRefEntry.name, '"assets.bundle"'); - test.equal(fileRefEntry.path, '"Resources/assets.bundle"'); - test.equal(fileRefEntry.sourceTree, '""'); - - test.done(); - }, - 'should add to the Resources PBXGroup group': function (test) { - var newFile = proj.addResourceFile('Resources/assets.bundle'), - resources = proj.pbxGroupByName('Resources'); - - test.equal(resources.children.length, 10); - test.done(); - }, - 'should have the right values for the PBXGroup entry': function (test) { - var newFile = proj.addResourceFile('Resources/assets.bundle'), - resources = proj.pbxGroupByName('Resources'), - resourceObj = resources.children[9]; - - test.equal(resourceObj.comment, 'assets.bundle'); - test.equal(resourceObj.value, newFile.fileRef); - test.done(); - }, - 'should add to the PBXSourcesBuildPhase': function (test) { - var newFile = proj.addResourceFile('Resources/assets.bundle'), - sources = proj.pbxResourcesBuildPhaseObj(); - - test.equal(sources.files.length, 13); - test.done(); - }, - 'should have the right values for the Sources entry': function (test) { - var newFile = proj.addResourceFile('Resources/assets.bundle'), - sources = proj.pbxResourcesBuildPhaseObj(), - sourceObj = sources.files[12]; - - test.equal(sourceObj.comment, 'assets.bundle in Resources'); - test.equal(sourceObj.value, newFile.uuid); - test.done(); - }, - 'should remove "Resources/" from path if group path is set': function (test) { - var resources = proj.pbxGroupByName('Resources'), - newFile; + const newFile = proj.addResourceFile('Resources/assets.bundle'); + const fileRefSection = proj.pbxFileReferenceSection(); + const fileRefEntry = fileRefSection[newFile.fileRef]; + + assert.equal(fileRefEntry.isa, 'PBXFileReference'); + assert.equal(fileRefEntry.fileEncoding, undefined); + assert.equal(fileRefEntry.lastKnownFileType, 'wrapper.plug-in'); + assert.equal(fileRefEntry.name, '"assets.bundle"'); + assert.equal(fileRefEntry.path, '"Resources/assets.bundle"'); + assert.equal(fileRefEntry.sourceTree, '""'); + }); + + it('should add to the Resources PBXGroup group', () => { + proj.addResourceFile('Resources/assets.bundle'); + const resources = proj.pbxGroupByName('Resources'); + + assert.equal(resources.children.length, 10); + }); + + it('should have the right values for the PBXGroup entry', () => { + const newFile = proj.addResourceFile('Resources/assets.bundle'); + const resources = proj.pbxGroupByName('Resources'); + const resourceObj = resources.children[9]; + + assert.equal(resourceObj.comment, 'assets.bundle'); + assert.equal(resourceObj.value, newFile.fileRef); + }); + + it('should add to the PBXSourcesBuildPhase', () => { + proj.addResourceFile('Resources/assets.bundle'); + const sources = proj.pbxResourcesBuildPhaseObj(); + + assert.equal(sources.files.length, 13); + }); + it('should have the right values for the Sources entry', () => { + const newFile = proj.addResourceFile('Resources/assets.bundle'); + const sources = proj.pbxResourcesBuildPhaseObj(); + const sourceObj = sources.files[12]; + + assert.equal(sourceObj.comment, 'assets.bundle in Resources'); + assert.equal(sourceObj.value, newFile.uuid); + }); + + it('should remove "Resources/" from path if group path is set', () => { + const resources = proj.pbxGroupByName('Resources'); resources.path = '"Test200/Resources"'; - newFile = proj.addResourceFile('Resources/assets.bundle'); - test.equal(newFile.path, 'assets.bundle'); - test.done(); - }, - 'when added with { plugin: true }': { + const newFile = proj.addResourceFile('Resources/assets.bundle'); + assert.equal(newFile.path, 'assets.bundle'); + }); - 'should add the PBXFileReference with the "Plugins" path': function (test) { + // + // { plugin: true } + // + describe('when added with { plugin: true }', () => { + it('should add the PBXFileReference with the "Plugins" path', () => { delete proj.pbxGroupByName('Plugins').path; - var newFile = proj.addResourceFile('Plugins/assets.bundle', - { plugin: true }), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; - - test.equal(fileRefEntry.isa, 'PBXFileReference'); - test.equal(fileRefEntry.fileEncoding, undefined); - test.equal(fileRefEntry.lastKnownFileType, 'wrapper.plug-in'); - test.equal(fileRefEntry.name, '"assets.bundle"'); - test.equal(fileRefEntry.path, '"Plugins/assets.bundle"'); - test.equal(fileRefEntry.sourceTree, '""'); - test.done(); - }, - - 'should add to the Plugins PBXGroup group': function (test) { - var newFile = proj.addResourceFile('Plugins/assets.bundle', - { plugin: true }), - plugins = proj.pbxGroupByName('Plugins'); - - test.equal(plugins.children.length, 1); - test.done(); - }, - - 'should have the Plugins values for the PBXGroup entry': function (test) { - var newFile = proj.addResourceFile('Plugins/assets.bundle', - { plugin: true }), - plugins = proj.pbxGroupByName('Plugins'), - pluginObj = plugins.children[0]; - - test.equal(pluginObj.comment, 'assets.bundle'); - test.equal(pluginObj.value, newFile.fileRef); - test.done(); - }, - - 'should add to the PBXSourcesBuildPhase': function (test) { - var newFile = proj.addResourceFile('Plugins/assets.bundle', - { plugin: true }), - sources = proj.pbxResourcesBuildPhaseObj(); - - test.equal(sources.files.length, 13); - test.done(); - }, - - 'should have the right values for the Sources entry': function (test) { - var newFile = proj.addResourceFile('Plugins/assets.bundle', - { plugin: true }), - sources = proj.pbxResourcesBuildPhaseObj(), - sourceObj = sources.files[12]; - - test.equal(sourceObj.comment, 'assets.bundle in Resources'); - test.equal(sourceObj.value, newFile.uuid); - test.done(); - }, - - 'should remove "Plugins/" from path if group path is set': function (test) { - var plugins = proj.pbxGroupByName('Plugins'), - newFile; + const newFile = proj.addResourceFile( + 'Plugins/assets.bundle', + { plugin: true } + ); + + const fileRefSection = proj.pbxFileReferenceSection(); + const fileRefEntry = fileRefSection[newFile.fileRef]; + + assert.equal(fileRefEntry.isa, 'PBXFileReference'); + assert.equal(fileRefEntry.fileEncoding, undefined); + assert.equal(fileRefEntry.lastKnownFileType, 'wrapper.plug-in'); + assert.equal(fileRefEntry.name, '"assets.bundle"'); + assert.equal(fileRefEntry.path, '"Plugins/assets.bundle"'); + assert.equal(fileRefEntry.sourceTree, '""'); + }); + + it('should add to the Plugins PBXGroup group', () => { + proj.addResourceFile('Plugins/assets.bundle', { plugin: true }); + const plugins = proj.pbxGroupByName('Plugins'); + + assert.equal(plugins.children.length, 1); + }); + + it('should have the Plugins values for the PBXGroup entry', () => { + const newFile = proj.addResourceFile( + 'Plugins/assets.bundle', + { plugin: true } + ); + + const plugins = proj.pbxGroupByName('Plugins'); + const pluginObj = plugins.children[0]; + assert.equal(pluginObj.comment, 'assets.bundle'); + assert.equal(pluginObj.value, newFile.fileRef); + }); + + it('should add to the PBXSourcesBuildPhase', () => { + proj.addResourceFile('Plugins/assets.bundle', { plugin: true }); + const sources = proj.pbxResourcesBuildPhaseObj(); + + assert.equal(sources.files.length, 13); + }); + + it('should have the right values for the Sources entry', () => { + const newFile = proj.addResourceFile( + 'Plugins/assets.bundle', + { plugin: true } + ); + + const sources = proj.pbxResourcesBuildPhaseObj(); + const sourceObj = sources.files[12]; + + assert.equal(sourceObj.comment, 'assets.bundle in Resources'); + assert.equal(sourceObj.value, newFile.uuid); + }); + + it('should remove "Plugins/" from path if group path is set', () => { + const plugins = proj.pbxGroupByName('Plugins'); plugins.path = '"Test200/Plugins"'; - newFile = proj.addResourceFile('Plugins/assets.bundle', - { plugin: true }); - - test.equal(newFile.path, 'assets.bundle'); - test.done(); - } - }, - 'when added with { variantGroup: true }': { - - 'should not add to the PBXResourcesBuildPhase and PBXBuildFile': function (test) { - var newFile = proj.addResourceFile('en.lproj/Localization.strings', - { variantGroup: true }); - - var sources = proj.pbxResourcesBuildPhaseObj(); - test.equal(sources.files.length, 12); - - var buildFileSection = proj.pbxBuildFileSection(); - test.ok(buildFileSection[newFile.uuid] === undefined); - - test.done(); - }, - - }, - 'duplicate entries': { - 'should return false': function (test) { - var newFile = proj.addResourceFile('Plugins/assets.bundle'); - - test.ok(!proj.addResourceFile('Plugins/assets.bundle')); - test.done(); - }, - 'should return false (plugin entries)': function (test) { - var newFile = proj.addResourceFile('Plugins/assets.bundle', - { plugin: true }); - - test.ok(!proj.addResourceFile('Plugins/assets.bundle', - { plugin: true })); - test.done(); - }, - 'should not add another entry anywhere': function (test) { - var newFile = proj.addResourceFile('Plugins/assets.bundle'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length, - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length, - resources = proj.pbxGroupByName('Resources'), - sources = proj.pbxResourcesBuildPhaseObj(); + + const newFile = proj.addResourceFile( + 'Plugins/assets.bundle', + { plugin: true } + ); + + assert.equal(newFile.path, 'assets.bundle'); + }); + }); + + // + // { variantGroup: true } + // + describe('when added with { variantGroup: true }', () => { + it('should not add to the PBXResourcesBuildPhase and PBXBuildFile', () => { + const newFile = proj.addResourceFile( + 'en.lproj/Localization.strings', + { variantGroup: true } + ); + + const sources = proj.pbxResourcesBuildPhaseObj(); + assert.equal(sources.files.length, 12); + + const buildFileSection = proj.pbxBuildFileSection(); + assert.ok(buildFileSection[newFile.uuid] === undefined); + }); + }); + + // + // duplicate entries + // + describe('duplicate entries', () => { + it('should return false', () => { + proj.addResourceFile('Plugins/assets.bundle'); + assert.ok(!proj.addResourceFile('Plugins/assets.bundle')); + }); + + it('should return false (plugin entries)', () => { + proj.addResourceFile('Plugins/assets.bundle', { plugin: true }); + assert.ok(!proj.addResourceFile('Plugins/assets.bundle', { plugin: true })); + }); + + it('should not add another entry anywhere', () => { + proj.addResourceFile('Plugins/assets.bundle'); + + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; + + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + + const resources = proj.pbxGroupByName('Resources'); + const sources = proj.pbxResourcesBuildPhaseObj(); proj.addResourceFile('Plugins/assets.bundle'); - // check lengths - test.equal(60, bfsLength); - test.equal(68, frsLength); - test.equal(resources.children.length, 10); - test.equal(sources.files.length, 13); - test.done(); - } - }, - tearDown: function (callback) { + assert.equal(60, bfsLength); + assert.equal(68, frsLength); + assert.equal(resources.children.length, 10); + assert.equal(sources.files.length, 13); + }); + }); + + afterEach(() => { delete proj.pbxGroupByName('Resources').path; - callback(); - } -} + }); +}); diff --git a/test/addSourceFile.js b/test/addSourceFile.js index d614d62c..409bad09 100644 --- a/test/addSourceFile.js +++ b/test/addSourceFile.js @@ -1,174 +1,165 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addSourceFile = { - 'should return a pbxFile': function (test) { - var newFile = proj.addSourceFile('file.m'); - - test.equal(newFile.constructor, pbxFile); - test.done() - }, - 'should set a uuid on the pbxFile': function (test) { - var newFile = proj.addSourceFile('file.m'); - - test.ok(newFile.uuid); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addSourceFile('file.m'); - - test.ok(newFile.fileRef); - test.done() - }, - 'should populate the PBXBuildFile section with 2 fields': function (test) { - var newFile = proj.addSourceFile('file.m'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; - - test.equal(60, bfsLength); - test.ok(buildFileSection[newFile.uuid]); - test.ok(buildFileSection[newFile.uuid + '_comment']); - - test.done(); - }, - 'should add the PBXBuildFile comment correctly': function (test) { - var newFile = proj.addSourceFile('file.m'), - commentKey = newFile.uuid + '_comment', - buildFileSection = proj.pbxBuildFileSection(); - - test.equal(buildFileSection[commentKey], 'file.m in Sources'); - test.done(); - }, - 'should add the PBXBuildFile object correctly': function (test) { - var newFile = proj.addSourceFile('file.m'), - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[newFile.uuid]; - - test.equal(buildFileEntry.isa, 'PBXBuildFile'); - test.equal(buildFileEntry.fileRef, newFile.fileRef); - test.equal(buildFileEntry.fileRef_comment, 'file.m'); - - test.done(); - }, - 'should populate the PBXFileReference section with 2 fields': function (test) { - var newFile = proj.addSourceFile('file.m'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(68, frsLength); - test.ok(fileRefSection[newFile.fileRef]); - test.ok(fileRefSection[newFile.fileRef + '_comment']); - - test.done(); - }, - 'should populate the PBXFileReference comment correctly': function (test) { - var newFile = proj.addSourceFile('file.m'), - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = newFile.fileRef + '_comment'; - - test.equal(fileRefSection[commentKey], 'file.m'); - test.done(); - }, - 'should add the PBXFileReference object correctly': function (test) { - var newFile = proj.addSourceFile('Plugins/file.m'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; - - test.equal(fileRefEntry.isa, 'PBXFileReference'); - test.equal(fileRefEntry.fileEncoding, 4); - test.equal(fileRefEntry.lastKnownFileType, 'sourcecode.c.objc'); - test.equal(fileRefEntry.name, '"file.m"'); - test.equal(fileRefEntry.path, '"file.m"'); - test.equal(fileRefEntry.sourceTree, '""'); - - test.done(); - }, - 'should add to the Plugins PBXGroup group': function (test) { - var newFile = proj.addSourceFile('Plugins/file.m'), - plugins = proj.pbxGroupByName('Plugins'); - - test.equal(plugins.children.length, 1); - test.done(); - }, - 'should have the right values for the PBXGroup entry': function (test) { - var newFile = proj.addSourceFile('Plugins/file.m'), - plugins = proj.pbxGroupByName('Plugins'), - pluginObj = plugins.children[0]; - - test.equal(pluginObj.comment, 'file.m'); - test.equal(pluginObj.value, newFile.fileRef); - test.done(); - }, - 'should add to the PBXSourcesBuildPhase': function (test) { - var newFile = proj.addSourceFile('Plugins/file.m'), - sources = proj.pbxSourcesBuildPhaseObj(); - - test.equal(sources.files.length, 3); - test.done(); - }, - 'should have the right values for the Sources entry': function (test) { - var newFile = proj.addSourceFile('Plugins/file.m'), - sources = proj.pbxSourcesBuildPhaseObj(), - sourceObj = sources.files[2]; - - test.equal(sourceObj.comment, 'file.m in Sources'); - test.equal(sourceObj.value, newFile.uuid); - test.done(); - }, - 'duplicate entries': { - 'should return false': function (test) { - var newFile = proj.addSourceFile('Plugins/file.m'); - - test.ok(!proj.addSourceFile('Plugins/file.m')); - test.done(); - }, - 'should not add another entry anywhere': function (test) { - var newFile = proj.addSourceFile('Plugins/file.m'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length, - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length, - plugins = proj.pbxGroupByName('Plugins'), - sources = proj.pbxSourcesBuildPhaseObj(); - - // duplicate! - proj.addSourceFile('Plugins/file.m'); - - test.equal(60, bfsLength); // BuildFileSection - test.equal(68, frsLength); // FileReferenceSection - test.equal(plugins.children.length, 1); // Plugins pbxGroup - test.equal(sources.files.length, 3); // SourcesBuildPhhase - test.done(); - } - } -} - +describe('addSourceFile', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxFile', () => { + const newFile = proj.addSourceFile('file.m'); + assert.strictEqual(newFile.constructor, PBXFile); + }); + + it('should set a uuid on the pbxFile', () => { + const newFile = proj.addSourceFile('file.m'); + assert.ok(newFile.uuid); + }); + + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addSourceFile('file.m'); + assert.ok(newFile.fileRef); + }); + + it('should populate the PBXBuildFile section with 2 fields', () => { + const newFile = proj.addSourceFile('file.m'); + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; + + assert.strictEqual(bfsLength, 60); + assert.ok(buildFileSection[newFile.uuid]); + assert.ok(buildFileSection[newFile.uuid + '_comment']); + }); + + it('should add the PBXBuildFile comment correctly', () => { + const newFile = proj.addSourceFile('file.m'); + const commentKey = newFile.uuid + '_comment'; + const buildFileSection = proj.pbxBuildFileSection(); + + assert.strictEqual(buildFileSection[commentKey], 'file.m in Sources'); + }); + + it('should add the PBXBuildFile object correctly', () => { + const newFile = proj.addSourceFile('file.m'); + const buildFileSection = proj.pbxBuildFileSection(); + const buildFileEntry = buildFileSection[newFile.uuid]; + + assert.strictEqual(buildFileEntry.isa, 'PBXBuildFile'); + assert.strictEqual(buildFileEntry.fileRef, newFile.fileRef); + assert.strictEqual(buildFileEntry.fileRef_comment, 'file.m'); + }); + + it('should populate the PBXFileReference section with 2 fields', () => { + const newFile = proj.addSourceFile('file.m'); + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + + assert.strictEqual(frsLength, 68); + assert.ok(fileRefSection[newFile.fileRef]); + assert.ok(fileRefSection[newFile.fileRef + '_comment']); + }); + + it('should populate the PBXFileReference comment correctly', () => { + const newFile = proj.addSourceFile('file.m'); + const fileRefSection = proj.pbxFileReferenceSection(); + const commentKey = newFile.fileRef + '_comment'; + + assert.strictEqual(fileRefSection[commentKey], 'file.m'); + }); + + it('should add the PBXFileReference object correctly', () => { + const newFile = proj.addSourceFile('Plugins/file.m'); + const fileRefSection = proj.pbxFileReferenceSection(); + const fileRefEntry = fileRefSection[newFile.fileRef]; + + assert.strictEqual(fileRefEntry.isa, 'PBXFileReference'); + assert.strictEqual(fileRefEntry.fileEncoding, 4); + assert.strictEqual(fileRefEntry.lastKnownFileType, 'sourcecode.c.objc'); + assert.strictEqual(fileRefEntry.name, '"file.m"'); + assert.strictEqual(fileRefEntry.path, '"file.m"'); + assert.strictEqual(fileRefEntry.sourceTree, '""'); + }); + + it('should add to the Plugins PBXGroup group', () => { + proj.addSourceFile('Plugins/file.m'); + + const plugins = proj.pbxGroupByName('Plugins'); + assert.strictEqual(plugins.children.length, 1); + }); + + it('should have the right values for the PBXGroup entry', () => { + const newFile = proj.addSourceFile('Plugins/file.m'); + const plugins = proj.pbxGroupByName('Plugins'); + const pluginObj = plugins.children[0]; + + assert.strictEqual(pluginObj.comment, 'file.m'); + assert.strictEqual(pluginObj.value, newFile.fileRef); + }); + + it('should add to the PBXSourcesBuildPhase', () => { + proj.addSourceFile('Plugins/file.m'); + + const sources = proj.pbxSourcesBuildPhaseObj(); + assert.strictEqual(sources.files.length, 3); + }); + + it('should have the right values for the Sources entry', () => { + const newFile = proj.addSourceFile('Plugins/file.m'); + const sources = proj.pbxSourcesBuildPhaseObj(); + const sourceObj = sources.files[2]; + + assert.strictEqual(sourceObj.comment, 'file.m in Sources'); + assert.strictEqual(sourceObj.value, newFile.uuid); + }); + + it('duplicate entries should return false', () => { + proj.addSourceFile('Plugins/file.m'); + assert.ok(!proj.addSourceFile('Plugins/file.m')); + }); + + it('duplicate entries should not add another entry anywhere', () => { + proj.addSourceFile('Plugins/file.m'); + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + const plugins = proj.pbxGroupByName('Plugins'); + const sources = proj.pbxSourcesBuildPhaseObj(); + + // duplicate! + proj.addSourceFile('Plugins/file.m'); + + assert.strictEqual(bfsLength, 60); + assert.strictEqual(frsLength, 68); + assert.strictEqual(plugins.children.length, 1); + assert.strictEqual(sources.files.length, 3); + }); +}); diff --git a/test/addStaticLibrary.js b/test/addStaticLibrary.js index d1b0ec61..9877d590 100644 --- a/test/addStaticLibrary.js +++ b/test/addStaticLibrary.js @@ -1,33 +1,38 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -function nonComments(obj) { - var keys = Object.keys(obj), - newObj = {}, i = 0; +function nonComments (obj) { + const keys = Object.keys(obj); + const newObj = {}; + let i = 0; for (i; i < keys.length; i++) { if (!/_comment$/.test(keys[i])) { @@ -38,231 +43,217 @@ function nonComments(obj) { return newObj; } -function librarySearchPaths(proj) { - var configs = nonComments(proj.pbxXCBuildConfigurationSection()), - allPaths = [], - ids = Object.keys(configs), i, buildSettings; +function librarySearchPaths (proj) { + const configs = nonComments(proj.pbxXCBuildConfigurationSection()); + const allPaths = []; + const ids = Object.keys(configs); + let i; + let buildSettings; - for (i = 0; i< ids.length; i++) { + for (i = 0; i < ids.length; i++) { buildSettings = configs[ids[i]].buildSettings; - if (buildSettings['LIBRARY_SEARCH_PATHS']) { - allPaths.push(buildSettings['LIBRARY_SEARCH_PATHS']); + if (buildSettings.LIBRARY_SEARCH_PATHS) { + allPaths.push(buildSettings.LIBRARY_SEARCH_PATHS); } } return allPaths; } -exports.setUp = function (callback) { +beforeEach(() => { proj.hash = cleanHash(); - callback(); -} - -exports.addStaticLibrary = { - 'should return a pbxFile': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); - - test.equal(newFile.constructor, pbxFile); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); - - test.ok(newFile.fileRef); - test.done() - }, - 'should populate the PBXBuildFile section with 2 fields': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; - - test.equal(60, bfsLength); - test.ok(buildFileSection[newFile.uuid]); - test.ok(buildFileSection[newFile.uuid + '_comment']); - - test.done(); - }, - 'should populate the PBXBuildFile section with 2 fields as plugin': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a', - { plugin: true }); - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; - - test.equal(60, bfsLength); - test.ok(buildFileSection[newFile.uuid]); - test.ok(buildFileSection[newFile.uuid + '_comment']); - - test.done(); - }, - 'should add the PBXBuildFile comment correctly': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); - commentKey = newFile.uuid + '_comment', - buildFileSection = proj.pbxBuildFileSection(); - - test.equal(buildFileSection[commentKey], 'libGoogleAnalytics.a in Frameworks'); - test.done(); - }, - 'should add the PBXBuildFile object correctly': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[newFile.uuid]; - - test.equal(buildFileEntry.isa, 'PBXBuildFile'); - test.equal(buildFileEntry.fileRef, newFile.fileRef); - test.equal(buildFileEntry.fileRef_comment, 'libGoogleAnalytics.a'); - - test.done(); - }, - 'should populate the PBXFileReference section with 2 fields': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(68, frsLength); - test.ok(fileRefSection[newFile.fileRef]); - test.ok(fileRefSection[newFile.fileRef + '_comment']); - - test.done(); - }, - 'should populate the PBXFileReference comment correctly': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = newFile.fileRef + '_comment'; - - test.equal(fileRefSection[commentKey], 'libGoogleAnalytics.a'); - test.done(); - }, - 'should add the PBXFileReference object correctly': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; - - test.equal(fileRefEntry.isa, 'PBXFileReference'); - test.equal(fileRefEntry.lastKnownFileType, 'archive.ar'); - test.equal(fileRefEntry.name, '"libGoogleAnalytics.a"'); - test.equal(fileRefEntry.path, '"libGoogleAnalytics.a"'); - test.equal(fileRefEntry.sourceTree, '""'); - - test.done(); - }, - 'should add to the PBXFrameworksBuildPhase': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'), - frameworks = proj.pbxFrameworksBuildPhaseObj(); - - test.equal(frameworks.files.length, 16); - test.done(); - }, - 'should have the right values for the Sources entry': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'), - frameworks = proj.pbxFrameworksBuildPhaseObj(), - framework = frameworks.files[15]; - - test.equal(framework.comment, 'libGoogleAnalytics.a in Frameworks'); - test.equal(framework.value, newFile.uuid); - test.done(); - }, - 'should set LIBRARY_SEARCH_PATHS for appropriate build configurations': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'), - configs = nonComments(proj.pbxXCBuildConfigurationSection()), - ids = Object.keys(configs), i, buildSettings; - - for (i = 0; i< ids.length; i++) { +}); + +describe('addStaticLibrary', () => { + it('should return a pbxFile', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + + assert.equal(newFile.constructor, PBXFile); + }); + + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + + assert.ok(newFile.fileRef); + }); + + it('should populate the PBXBuildFile section with 2 fields', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; + + assert.equal(60, bfsLength); + assert.ok(buildFileSection[newFile.uuid]); + assert.ok(buildFileSection[newFile.uuid + '_comment']); + }); + + it('should populate the PBXBuildFile section with 2 fields as plugin', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a', { plugin: true }); + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; + + assert.equal(60, bfsLength); + assert.ok(buildFileSection[newFile.uuid]); + assert.ok(buildFileSection[newFile.uuid + '_comment']); + }); + + it('should add the PBXBuildFile comment correctly', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + const commentKey = newFile.uuid + '_comment'; + const buildFileSection = proj.pbxBuildFileSection(); + + assert.equal(buildFileSection[commentKey], 'libGoogleAnalytics.a in Frameworks'); + }); + + it('should add the PBXBuildFile object correctly', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + const buildFileSection = proj.pbxBuildFileSection(); + const buildFileEntry = buildFileSection[newFile.uuid]; + + assert.equal(buildFileEntry.isa, 'PBXBuildFile'); + assert.equal(buildFileEntry.fileRef, newFile.fileRef); + assert.equal(buildFileEntry.fileRef_comment, 'libGoogleAnalytics.a'); + }); + + it('should populate the PBXFileReference section with 2 fields', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + + assert.equal(68, frsLength); + assert.ok(fileRefSection[newFile.fileRef]); + assert.ok(fileRefSection[newFile.fileRef + '_comment']); + }); + + it('should populate the PBXFileReference comment correctly', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + const fileRefSection = proj.pbxFileReferenceSection(); + const commentKey = newFile.fileRef + '_comment'; + + assert.equal(fileRefSection[commentKey], 'libGoogleAnalytics.a'); + }); + + it('should add the PBXFileReference object correctly', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + const fileRefSection = proj.pbxFileReferenceSection(); + const fileRefEntry = fileRefSection[newFile.fileRef]; + + assert.equal(fileRefEntry.isa, 'PBXFileReference'); + assert.equal(fileRefEntry.lastKnownFileType, 'archive.ar'); + assert.equal(fileRefEntry.name, '"libGoogleAnalytics.a"'); + assert.equal(fileRefEntry.path, '"libGoogleAnalytics.a"'); + assert.equal(fileRefEntry.sourceTree, '""'); + }); + + it('should add to the PBXFrameworksBuildPhase', () => { + proj.addStaticLibrary('libGoogleAnalytics.a'); + const frameworks = proj.pbxFrameworksBuildPhaseObj(); + + assert.equal(frameworks.files.length, 16); + }); + + it('should have the right values for the Sources entry', () => { + const newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); + const frameworks = proj.pbxFrameworksBuildPhaseObj(); + const framework = frameworks.files[15]; + + assert.equal(framework.comment, 'libGoogleAnalytics.a in Frameworks'); + assert.equal(framework.value, newFile.uuid); + }); + + it('should set LIBRARY_SEARCH_PATHS for appropriate build configurations', () => { + proj.addStaticLibrary('libGoogleAnalytics.a'); + const configs = nonComments(proj.pbxXCBuildConfigurationSection()); + const ids = Object.keys(configs); + let i; + let buildSettings; + + for (i = 0; i < ids.length; i++) { buildSettings = configs[ids[i]].buildSettings; - if (buildSettings['PRODUCT_NAME'] == '"KitchenSinktablet"') { - test.ok(buildSettings['LIBRARY_SEARCH_PATHS']); + if (buildSettings.PRODUCT_NAME === '"KitchenSinktablet"') { + assert.ok(buildSettings.LIBRARY_SEARCH_PATHS); } } + }); - test.done(); - }, - 'should ensure LIBRARY_SEARCH_PATHS inherits defaults correctly': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'), - libraryPaths = librarySearchPaths(proj), - expectedPath = '"\\"$(SRCROOT)/KitchenSinktablet\\""', - i, current; + it('should ensure LIBRARY_SEARCH_PATHS inherits defaults correctly', () => { + proj.addStaticLibrary('libGoogleAnalytics.a'); + const libraryPaths = librarySearchPaths(proj); + let i; + let current; for (i = 0; i < libraryPaths.length; i++) { current = libraryPaths[i]; - test.ok(current.indexOf('"$(inherited)"') >= 0); + assert.ok(current.indexOf('"$(inherited)"') >= 0); } + }); - test.done(); - }, - 'should ensure the new library is in LIBRARY_SEARCH_PATHS': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'), - libraryPaths = librarySearchPaths(proj), - expectedPath = '"\\"$(SRCROOT)/KitchenSinktablet\\""', - i, current; + it('should ensure the new library is in LIBRARY_SEARCH_PATHS', () => { + proj.addStaticLibrary('libGoogleAnalytics.a'); + const libraryPaths = librarySearchPaths(proj); + const expectedPath = '"\\"$(SRCROOT)/KitchenSinktablet\\""'; + let i; + let current; for (i = 0; i < libraryPaths.length; i++) { current = libraryPaths[i]; - test.ok(current.indexOf(expectedPath) >= 0); + assert.ok(current.indexOf(expectedPath) >= 0); } + }); + + it('should add to the Plugins group, optionally', () => { + proj.addStaticLibrary('libGoogleAnalytics.a', { plugin: true }); + const plugins = proj.pbxGroupByName('Plugins'); + + assert.equal(plugins.children.length, 1); + }); - test.done(); - }, - 'should add to the Plugins group, optionally': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a', - { plugin: true }), - plugins = proj.pbxGroupByName('Plugins'); - - test.equal(plugins.children.length, 1); - test.done(); - }, - 'should add the right LIBRARY_SEARCH_PATHS entry for plugins': { - 'with group set': function (test) { - plugins = proj.pbxGroupByName('Plugins'); + describe('should add the right LIBRARY_SEARCH_PATHS entry for plugins', () => { + it('with group set', () => { + const plugins = proj.pbxGroupByName('Plugins'); plugins.path = '"Test200/Plugins"'; - var newFile = proj.addStaticLibrary('Plugins/libGoogleAnalytics.a', - { plugin: true }), - libraryPaths = librarySearchPaths(proj), - expectedPath = '"\\"$(SRCROOT)/Test200/Plugins\\""', - i, current; + proj.addStaticLibrary('Plugins/libGoogleAnalytics.a', { plugin: true }); + const libraryPaths = librarySearchPaths(proj); + const expectedPath = '"\\"$(SRCROOT)/Test200/Plugins\\""'; + let current; - for (i = 0; i < libraryPaths.length; i++) { + for (let i = 0; i < libraryPaths.length; i++) { current = libraryPaths[i]; - test.ok(current.indexOf(expectedPath) >= 0, - expectedPath + ' not found in ' + current); + assert.ok(current.indexOf(expectedPath) >= 0, + expectedPath + ' not found in ' + current); } + }); - test.done(); - }, - 'without group set': function (test) { - plugins = proj.pbxGroupByName('Plugins'); + it('without group set', () => { + const plugins = proj.pbxGroupByName('Plugins'); delete plugins.path; - var newFile = proj.addStaticLibrary('Plugins/libGoogleAnalytics.a', - { plugin: true }), - libraryPaths = librarySearchPaths(proj), - expectedPath = '"\\"$(SRCROOT)/KitchenSinktablet/Plugins\\""', - i, current; + proj.addStaticLibrary('Plugins/libGoogleAnalytics.a', { plugin: true }); + const libraryPaths = librarySearchPaths(proj); + const expectedPath = '"\\"$(SRCROOT)/KitchenSinktablet/Plugins\\""'; + let current; - for (i = 0; i < libraryPaths.length; i++) { + for (let i = 0; i < libraryPaths.length; i++) { current = libraryPaths[i]; - test.ok(current.indexOf(expectedPath) >= 0, - expectedPath + ' not found in ' + current); + assert.ok(current.indexOf(expectedPath) >= 0, + expectedPath + ' not found in ' + current); } - - test.done(); - } - }, - 'duplicate entries': { - 'should return false': function (test) { - var newFile = proj.addStaticLibrary('libGoogleAnalytics.a'); - - test.ok(!proj.addStaticLibrary('libGoogleAnalytics.a')); - test.done(); - }, - 'should return false (plugin entries)': function (test) { - var newFile = proj.addStaticLibrary('Plugins/libGoogleAnalytics.a', - { plugin: true }); - - test.ok(!proj.addStaticLibrary('Plugins/libGoogleAnalytics.a', - { plugin: true })); - test.done(); - }, - } -} + }); + }); + + describe('duplicate entries', () => { + it('should return false', () => { + proj.addStaticLibrary('libGoogleAnalytics.a'); + + assert.ok(!proj.addStaticLibrary('libGoogleAnalytics.a')); + }); + it('should return false (plugin entries)', () => { + proj.addStaticLibrary('Plugins/libGoogleAnalytics.a', { plugin: true }); + + assert.ok(!proj.addStaticLibrary('Plugins/libGoogleAnalytics.a', { plugin: true })); + }); + }); +}); diff --git a/test/addTarget.js b/test/addTarget.js index 6e446250..4ae0dd8a 100644 --- a/test/addTarget.js +++ b/test/addTarget.js @@ -1,391 +1,386 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -var TARGET_NAME = 'TestExtension', - TARGET_TYPE = 'app_extension', - TARGET_SUBFOLDER_NAME = 'TestExtensionFiles'; +const TARGET_NAME = 'TestExtension'; +const TARGET_TYPE = 'app_extension'; +const TARGET_SUBFOLDER_NAME = 'TestExtensionFiles'; +const TARGET_BUNDLE_ID = 'com.cordova.test.appextension'; -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('addTarget', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.addTarget = { - 'should throw when target name is missing': function (test) { - test.throws(function() { + it('should throw when target name is missing', () => { + assert.throws(function () { proj.addTarget(null, TARGET_TYPE); }); + }); - test.done(); - }, - 'should throw when provided blank or empty target name': function (test) { - test.throws(function() { + it('should throw when provided blank or empty target name', () => { + assert.throws(function () { proj.addTarget('', TARGET_TYPE); }, function (error) { return (error instanceof Error) && /Target name missing/i.test(error); }); - test.throws(function() { + assert.throws(function () { proj.addTarget(' ', TARGET_TYPE); }, function (error) { return (error instanceof Error) && /Target name missing/i.test(error); }); + }); - test.done(); - }, - 'should throw when target type missing': function (test) { - test.throws(function() { + it('should throw when target type missing', () => { + assert.throws(function () { proj.addTarget(TARGET_NAME, null); }, function (error) { return (error instanceof Error) && /Target type missing/i.test(error); }); + }); - test.done(); - }, - 'should throw when invalid target type': function (test) { - test.throws(function() { + it('should throw when invalid target type', () => { + assert.throws(function () { proj.addTarget(TARGET_NAME, 'invalid_target_type'); }, function (error) { return (error instanceof Error) && /Target type invalid/i.test(error); }); - - test.done(); - }, - 'should create a new target': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.done(); - }, - 'should add debug and release configurations to build configuration list': function (test) { - var pbxXCBuildConfigurationSection = proj.pbxXCBuildConfigurationSection(), - pbxXCConfigurationList = proj.pbxXCConfigurationList(), - target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(pbxXCConfigurationList[target.pbxNativeTarget.buildConfigurationList]); - var buildConfigurations = pbxXCConfigurationList[target.pbxNativeTarget.buildConfigurationList].buildConfigurations; - test.ok(buildConfigurations); - test.equal(buildConfigurations.length, 2); + }); + + it('should create a new target', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + }); + + it('should create a new target with bundleid', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME, TARGET_BUNDLE_ID); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + }); + + it('should add debug and release configurations to build configuration list', () => { + const pbxXCBuildConfigurationSection = proj.pbxXCBuildConfigurationSection(); + const pbxXCConfigurationList = proj.pbxXCConfigurationList(); + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(pbxXCConfigurationList[target.pbxNativeTarget.buildConfigurationList]); + const buildConfigurations = pbxXCConfigurationList[target.pbxNativeTarget.buildConfigurationList].buildConfigurations; + assert.ok(buildConfigurations); + assert.equal(buildConfigurations.length, 2); buildConfigurations.forEach((config, index) => { - var configUuid = config.value; - test.ok(configUuid); - var pbxConfig = pbxXCBuildConfigurationSection[configUuid]; - test.ok(pbxConfig); - test.equal(pbxConfig.name, index === 0 ? 'Debug' : 'Release'); - test.equal(pbxConfig.isa, 'XCBuildConfiguration'); - test.ok(pbxConfig.buildSettings); + const configUuid = config.value; + assert.ok(configUuid); + const pbxConfig = pbxXCBuildConfigurationSection[configUuid]; + assert.ok(pbxConfig); + assert.equal(pbxConfig.name, index === 0 ? 'Debug' : 'Release'); + assert.equal(pbxConfig.isa, 'XCBuildConfiguration'); + assert.ok(pbxConfig.buildSettings); if (index === 0) { - var debugConfig = pbxConfig.buildSettings['GCC_PREPROCESSOR_DEFINITIONS']; - test.ok(debugConfig); - test.equal(debugConfig.length, 2); - test.equal(debugConfig[0], '"DEBUG=1"'); - test.equal(debugConfig[1], '"$(inherited)"'); + const debugConfig = pbxConfig.buildSettings.GCC_PREPROCESSOR_DEFINITIONS; + assert.ok(debugConfig); + assert.equal(debugConfig.length, 2); + assert.equal(debugConfig[0], '"DEBUG=1"'); + assert.equal(debugConfig[1], '"$(inherited)"'); } - test.equal(pbxConfig.buildSettings['INFOPLIST_FILE'], '"' + TARGET_SUBFOLDER_NAME + '/' + TARGET_SUBFOLDER_NAME + '-Info.plist"'); - test.equal(pbxConfig.buildSettings['LD_RUNPATH_SEARCH_PATHS'], '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"'); - test.equal(pbxConfig.buildSettings['PRODUCT_NAME'], '"' + TARGET_NAME + '"'); - test.equal(pbxConfig.buildSettings['SKIP_INSTALL'], 'YES'); + assert.equal(pbxConfig.buildSettings.INFOPLIST_FILE, '"' + TARGET_SUBFOLDER_NAME + '/' + TARGET_SUBFOLDER_NAME + '-Info.plist"'); + assert.equal(pbxConfig.buildSettings.LD_RUNPATH_SEARCH_PATHS, '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"'); + assert.equal(pbxConfig.buildSettings.PRODUCT_NAME, '"' + TARGET_NAME + '"'); + assert.equal(pbxConfig.buildSettings.SKIP_INSTALL, 'YES'); }); - - test.done(); - }, - 'should add to build configuration list with default configuration name': function (test) { - var pbxXCConfigurationList = proj.pbxXCConfigurationList(), - target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(pbxXCConfigurationList[target.pbxNativeTarget.buildConfigurationList]); - test.equal(pbxXCConfigurationList[target.pbxNativeTarget.buildConfigurationList].defaultConfigurationName, 'Release'); - - test.done(); - }, - 'should add to build configuration list with comment': function (test) { - var pbxXCConfigurationList = proj.pbxXCConfigurationList(), - target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - var buildCommentKey = target.pbxNativeTarget.buildConfigurationList + '_comment'; - test.ok(pbxXCConfigurationList[buildCommentKey]); - test.equals(pbxXCConfigurationList[buildCommentKey], 'Build configuration list for PBXNativeTarget "' + TARGET_NAME + '"'); - - test.done(); - }, - 'should create a new target and add source, framework, resource and header files and the corresponding build phases': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME), - options = { 'target' : target.uuid }; - - var sourceFile = proj.addSourceFile('Plugins/file.m', options), - sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid), - resourceFile = proj.addResourceFile('assets.bundle', options), - resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid), - frameworkFile = proj.addFramework('libsqlite3.dylib', options); - frameworkPhase = proj.addBuildPhase([], 'PBXFrameworkBuildPhase', 'Frameworks', target.uuid), - headerFile = proj.addHeaderFile('file.h', options); - - test.ok(sourcePhase); - test.ok(resourcePhase); - test.ok(frameworkPhase); - - test.equal(sourceFile.constructor, pbxFile); - test.equal(resourceFile.constructor, pbxFile); - test.equal(frameworkFile.constructor, pbxFile); - test.equal(headerFile.constructor, pbxFile); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.done(); - }, - 'should create target with correct pbxNativeTarget name': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - var quotedTargetName = '"' + TARGET_NAME + '"'; - test.equals(target.pbxNativeTarget.name, quotedTargetName); - test.equals(target.pbxNativeTarget.productName, quotedTargetName); - - test.done(); - }, - 'should add build phase for extension target': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - test.ok(target.uuid); - - var phases = proj.pbxCopyfilesBuildPhaseObj(target.uuid); - test.ok(phases); - test.ok(phases.files); - test.equal(phases.files.length, 1); - - test.done(); - }, - 'should not add build phase for non-extension target': function (test) { - var target = proj.addTarget(TARGET_NAME, 'application'); - test.ok(target.uuid); - - var phases = proj.pbxCopyfilesBuildPhaseObj(target.uuid); - test.ok(!phases); - - test.done(); - }, - 'should add target as a target dependency to the main target': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - test.ok(target); - test.ok(target.uuid); - - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency']; - - var targetDependencyUuid = Object.keys(pbxTargetDependencySection).find( (key) => pbxTargetDependencySection[key].target === target.uuid); - test.ok(targetDependencyUuid); - - var firstTarget = proj.getFirstTarget(); - test.ok(firstTarget); - test.ok(firstTarget.firstTarget); - test.ok(firstTarget.firstTarget.dependencies); - - var firstTargetMatchingDependency = firstTarget.firstTarget.dependencies.find( (elem) => elem.value === targetDependencyUuid); - test.ok(firstTargetMatchingDependency); - - test.done(); - }, - 'should have "wrapper.application" filetype for application product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'application'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.application"'); - - test.done(); - }, - 'should have "wrapper.app-extension" filetype for app_extension product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'app_extension'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.app-extension"'); - - test.done(); - }, - 'should have "wrapper.plug-in" filetype for bundle product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'bundle'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.plug-in"'); - - test.done(); - }, - 'should have "compiled.mach-o.dylib" filetype for command_line_tool product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'command_line_tool'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"compiled.mach-o.dylib"'); - - test.done(); - }, - 'should have "compiled.mach-o.dylib" filetype for dynamic_library product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'dynamic_library'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"compiled.mach-o.dylib"'); - - test.done(); - }, - 'should have "wrapper.framework" filetype for framework product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'framework'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.framework"'); - - test.done(); - }, - 'should have "archive.ar" filetype for static_library product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'static_library'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"archive.ar"'); - - test.done(); - }, - 'should have "wrapper.cfbundle" filetype for unit_test_bundle product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'unit_test_bundle'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.cfbundle"'); - - test.done(); - }, - 'should have "wrapper.application" filetype for watch_app product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'watch_app'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.application"'); - - test.done(); - }, - 'should have "wrapper.application" filetype for watch2_app product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'watch2_app'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.application"'); - - test.done(); - }, - 'should have "wrapper.app-extension" filetype for watch_extension product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'watch_extension'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.app-extension"'); - - test.done(); - }, - 'should have "wrapper.app-extension" filetype for watch2_extension product': function (test) { - var target = proj.addTarget(TARGET_NAME, 'watch2_extension'); - test.ok(target); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.productReference); - - var productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; - test.ok(productFile); - test.ok(productFile.explicitFileType); - test.equal(productFile.explicitFileType, '"wrapper.app-extension"'); - - test.done(); - } -} + }); + + it('should add to build configuration list with default configuration name', () => { + const pbxXCConfigurationList = proj.pbxXCConfigurationList(); + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(pbxXCConfigurationList[target.pbxNativeTarget.buildConfigurationList]); + assert.equal(pbxXCConfigurationList[target.pbxNativeTarget.buildConfigurationList].defaultConfigurationName, 'Release'); + }); + + it('should add to build configuration list with comment', () => { + const pbxXCConfigurationList = proj.pbxXCConfigurationList(); + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + const buildCommentKey = target.pbxNativeTarget.buildConfigurationList + '_comment'; + assert.ok(pbxXCConfigurationList[buildCommentKey]); + assert.equal(pbxXCConfigurationList[buildCommentKey], 'Build configuration list for PBXNativeTarget "' + TARGET_NAME + '"'); + }); + + it('should create a new target and add source, framework, resource and header files and the corresponding build phases', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + const options = { target: target.uuid }; + + const sourceFile = proj.addSourceFile('Plugins/file.m', options); + const sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid); + const resourceFile = proj.addResourceFile('assets.bundle', options); + const resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid); + const frameworkFile = proj.addFramework('libsqlite3.dylib', options); + const frameworkPhase = proj.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', target.uuid); + const headerFile = proj.addHeaderFile('file.h', options); + + assert.ok(sourcePhase); + assert.ok(resourcePhase); + assert.ok(frameworkPhase); + + assert.equal(sourceFile.constructor, PBXFile); + assert.equal(resourceFile.constructor, PBXFile); + assert.equal(frameworkFile.constructor, PBXFile); + assert.equal(headerFile.constructor, PBXFile); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + }); + + it('should create target with correct pbxNativeTarget name', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + const quotedTargetName = '"' + TARGET_NAME + '"'; + assert.equal(target.pbxNativeTarget.name, quotedTargetName); + assert.equal(target.pbxNativeTarget.productName, quotedTargetName); + }); + + it('should add build phase for extension target', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + assert.ok(target.uuid); + + const phases = proj.pbxCopyfilesBuildPhaseObj(target.uuid); + assert.ok(phases); + assert.ok(phases.files); + assert.equal(phases.files.length, 1); + }); + + it('should not add build phase for non-extension target', () => { + const target = proj.addTarget(TARGET_NAME, 'application'); + assert.ok(target.uuid); + + const phases = proj.pbxCopyfilesBuildPhaseObj(target.uuid); + assert.ok(!phases); + }); + + it('should add target as a target dependency to the main target', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + assert.ok(target); + assert.ok(target.uuid); + + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + + const targetDependencyUuid = Object.keys(pbxTargetDependencySection).find((key) => pbxTargetDependencySection[key].target === target.uuid); + assert.ok(targetDependencyUuid); + + const firstTarget = proj.getFirstTarget(); + assert.ok(firstTarget); + assert.ok(firstTarget.firstTarget); + assert.ok(firstTarget.firstTarget.dependencies); + + const firstTargetMatchingDependency = firstTarget.firstTarget.dependencies.find((elem) => elem.value === targetDependencyUuid); + assert.ok(firstTargetMatchingDependency); + }); + + it('should have "wrapper.application" filetype for application product', () => { + const target = proj.addTarget(TARGET_NAME, 'application'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.application"'); + }); + + it('should have "wrapper.app-extension" filetype for app_extension product', () => { + const target = proj.addTarget(TARGET_NAME, 'app_extension'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.app-extension"'); + }); + + it('should have "wrapper.plug-in" filetype for bundle product', () => { + const target = proj.addTarget(TARGET_NAME, 'bundle'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.plug-in"'); + }); + + it('should have "compiled.mach-o.dylib" filetype for command_line_tool product', () => { + const target = proj.addTarget(TARGET_NAME, 'command_line_tool'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"compiled.mach-o.dylib"'); + }); + + it('should have "compiled.mach-o.dylib" filetype for dynamic_library product', () => { + const target = proj.addTarget(TARGET_NAME, 'dynamic_library'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"compiled.mach-o.dylib"'); + }); + + it('should have "wrapper.framework" filetype for framework product', () => { + const target = proj.addTarget(TARGET_NAME, 'framework'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.framework"'); + }); + + it('should have "archive.ar" filetype for static_library product', () => { + const target = proj.addTarget(TARGET_NAME, 'static_library'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"archive.ar"'); + }); + + it('should have "wrapper.cfbundle" filetype for unit_test_bundle product', () => { + const target = proj.addTarget(TARGET_NAME, 'unit_test_bundle'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.cfbundle"'); + }); + + it('should have "wrapper.application" filetype for watch_app product', () => { + const target = proj.addTarget(TARGET_NAME, 'watch_app'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.application"'); + }); + + it('should have "wrapper.application" filetype for watch2_app product', () => { + const target = proj.addTarget(TARGET_NAME, 'watch2_app'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.application"'); + }); + + it('should have "wrapper.app-extension" filetype for watch_extension product', () => { + const target = proj.addTarget(TARGET_NAME, 'watch_extension'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.app-extension"'); + }); + + it('should have "wrapper.app-extension" filetype for watch2_extension product', () => { + const target = proj.addTarget(TARGET_NAME, 'watch2_extension'); + assert.ok(target); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.productReference); + + const productFile = proj.pbxFileReferenceSection()[target.pbxNativeTarget.productReference]; + assert.ok(productFile); + assert.ok(productFile.explicitFileType); + assert.equal(productFile.explicitFileType, '"wrapper.app-extension"'); + }); +}); diff --git a/test/addTargetDependency.js b/test/addTargetDependency.js index 37fe8293..d1f2ef58 100644 --- a/test/addTargetDependency.js +++ b/test/addTargetDependency.js @@ -1,239 +1,230 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('addTargetDependency', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + it('should return undefined when no target specified', () => { + const buildPhase = proj.addTargetDependency(); -exports.addTargetDependency = { - 'should return undefined when no target specified': function (test) { - var buildPhase = proj.addTargetDependency(); + assert.ok(typeof buildPhase === 'undefined'); + }); - test.ok(typeof buildPhase === 'undefined'); - test.done() - }, - 'should throw when target not found in nativeTargetsSection': function (test) { - test.throws(function() { + it('should throw when target not found in nativeTargetsSection', () => { + assert.throws(function () { proj.addTargetDependency('invalidTarget'); }, function (error) { return (error instanceof Error) && /Invalid target/i.test(error); }); - test.done() - }, - 'should throw when any dependency target not found in nativeTargetsSection': function (test) { - test.throws(function() { + }); + + it('should throw when any dependency target not found in nativeTargetsSection', () => { + assert.throws(function () { proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['invalidTarget']); }, function (error) { return (error instanceof Error) && /Invalid target/i.test(error); }); - test.done() - }, - 'should return the pbxTarget': function (test) { - var target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54']); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.target); - test.done(); - }, - 'should add targetDependencies to target': function (test) { - var targetInPbxProj = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB55']; - test.deepEqual(targetInPbxProj.dependencies, []); - - var target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - test.deepEqual(targetInPbxProj.dependencies, target.dependencies) - test.done() - }, - 'should not modify native target dependencies if PBXTargetDependency object does not exist': function (test) { - delete proj.hash.project.objects['PBXTargetDependency']; - - var numDependenciesBefore = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB54'].dependencies.length; + }); + + it('should return the pbxTarget', () => { + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54']); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.target); + }); + + it('should add targetDependencies to target', () => { + const targetInPbxProj = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB55']; + assert.deepEqual(targetInPbxProj.dependencies, []); + + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + assert.deepEqual(targetInPbxProj.dependencies, target.dependencies); + }); + + it('should not modify native target dependencies if PBXTargetDependency object does not exist', () => { + delete proj.hash.project.objects.PBXTargetDependency; + + const numDependenciesBefore = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB54'].dependencies.length; proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54']); - var numDependenciesAfter = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB54'].dependencies.length; + const numDependenciesAfter = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB54'].dependencies.length; - test.equal(numDependenciesBefore, numDependenciesAfter); + assert.equal(numDependenciesBefore, numDependenciesAfter); + }); - test.done(); - }, - 'should not modify native target dependencies if PBXContainerItemProxy object does not exist': function (test) { - delete proj.hash.project.objects['PBXContainerItemProxy']; + it('should not modify native target dependencies if PBXContainerItemProxy object does not exist', () => { + delete proj.hash.project.objects.PBXContainerItemProxy; - var numDependenciesBefore = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB54'].dependencies.length; + const numDependenciesBefore = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB54'].dependencies.length; proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54']); - var numDependenciesAfter = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB54'].dependencies.length; + const numDependenciesAfter = proj.pbxNativeTargetSection()['1D6058900D05DD3D006BFB54'].dependencies.length; - test.equal(numDependenciesBefore, numDependenciesAfter); + assert.equal(numDependenciesBefore, numDependenciesAfter); + }); - test.done(); - }, - 'should create a PBXTargetDependency for each dependency target': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + it('should create a PBXTargetDependency for each dependency target', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - for (var index = 0; index < target.dependencies.length; index++) { - var dependency = target.dependencies[index].value; - test.ok(pbxTargetDependencySection[dependency]); + for (let index = 0; index < target.dependencies.length; index++) { + const dependency = target.dependencies[index].value; + assert.ok(pbxTargetDependencySection[dependency]); } + }); - test.done() - }, - 'should set right comment for each target dependency': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + it('should set right comment for each target dependency', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - for (var index = 0; index < target.dependencies.length; index++) { - var dependencyCommentKey = target.dependencies[index].value + '_comment'; - test.equal(pbxTargetDependencySection[dependencyCommentKey], 'PBXTargetDependency'); + for (let index = 0; index < target.dependencies.length; index++) { + const dependencyCommentKey = target.dependencies[index].value + '_comment'; + assert.equal(pbxTargetDependencySection[dependencyCommentKey], 'PBXTargetDependency'); } + }); - test.done() - }, - 'should set right comment for each dependency target': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + it('should set right comment for each dependency target', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - for (var index = 0; index < target.dependencies.length; index++) { - var dependencyTargetUuid = target.dependencies[index].value; - var targetDependencyUuid = pbxTargetDependencySection[dependencyTargetUuid].target; + for (let index = 0; index < target.dependencies.length; index++) { + const dependencyTargetUuid = target.dependencies[index].value; + const targetDependencyUuid = pbxTargetDependencySection[dependencyTargetUuid].target; if (pbxTargetDependencySection[dependencyTargetUuid].target) { - var targetCommentKey = targetDependencyUuid + '_comment'; - test.equal(pbxTargetDependencySection[dependencyTargetUuid].target_comment, proj.pbxNativeTargetSection()[targetCommentKey]); + const targetCommentKey = targetDependencyUuid + '_comment'; + assert.equal(pbxTargetDependencySection[dependencyTargetUuid].target_comment, proj.pbxNativeTargetSection()[targetCommentKey]); } } + }); - test.done(); - }, - 'should create a PBXContainerItemProxy for each PBXTargetDependency': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - pbxContainerItemProxySection = proj.hash.project.objects['PBXContainerItemProxy'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + it('should create a PBXContainerItemProxy for each PBXTargetDependency', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const pbxContainerItemProxySection = proj.hash.project.objects.PBXContainerItemProxy; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - for (var index = 0; index < target.dependencies.length; index++) { - var dependency = target.dependencies[index].value, - targetProxy = pbxTargetDependencySection[dependency]['targetProxy']; + for (let index = 0; index < target.dependencies.length; index++) { + const dependency = target.dependencies[index].value; + const targetProxy = pbxTargetDependencySection[dependency].targetProxy; - test.ok(pbxContainerItemProxySection[targetProxy]); + assert.ok(pbxContainerItemProxySection[targetProxy]); } + }); - test.done() - }, - 'should set right comment for each container item proxy': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - pbxContainerItemProxySection = proj.hash.project.objects['PBXContainerItemProxy'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + it('should set right comment for each container item proxy', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const pbxContainerItemProxySection = proj.hash.project.objects.PBXContainerItemProxy; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB54', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - for (var index = 0; index < target.dependencies.length; index++) { - var dependencyTargetUuid = target.dependencies[index].value; + for (let index = 0; index < target.dependencies.length; index++) { + const dependencyTargetUuid = target.dependencies[index].value; - var proxyUuid = pbxTargetDependencySection[dependencyTargetUuid].targetProxy; + const proxyUuid = pbxTargetDependencySection[dependencyTargetUuid].targetProxy; if (proxyUuid) { - test.ok(pbxTargetDependencySection[dependencyTargetUuid].targetProxy_comment, 'PBXContainerItemProxy'); - test.ok(pbxContainerItemProxySection[proxyUuid]); - var proxyCommentKey = proxyUuid + '_comment'; - test.ok(pbxContainerItemProxySection[proxyCommentKey]); + assert.ok(pbxTargetDependencySection[dependencyTargetUuid].targetProxy_comment, 'PBXContainerItemProxy'); + assert.ok(pbxContainerItemProxySection[proxyUuid]); + const proxyCommentKey = proxyUuid + '_comment'; + assert.ok(pbxContainerItemProxySection[proxyCommentKey]); } } + }); - test.done(); - }, - 'should set each PBXContainerItemProxy`s remoteGlobalIDString correctly': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - pbxContainerItemProxySection = proj.hash.project.objects['PBXContainerItemProxy'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target, - remoteGlobalIDStrings = []; + it('should set each PBXContainerItemProxy`s remoteGlobalIDString correctly', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const pbxContainerItemProxySection = proj.hash.project.objects.PBXContainerItemProxy; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + const remoteGlobalIDStrings = []; - for (var index = 0; index < target.dependencies.length; index++) { - var dependency = target.dependencies[index].value, - targetProxy = pbxTargetDependencySection[dependency]['targetProxy']; + for (let index = 0; index < target.dependencies.length; index++) { + const dependency = target.dependencies[index].value; + const targetProxy = pbxTargetDependencySection[dependency].targetProxy; - remoteGlobalIDStrings.push(pbxContainerItemProxySection[targetProxy]['remoteGlobalIDString']); + remoteGlobalIDStrings.push(pbxContainerItemProxySection[targetProxy].remoteGlobalIDString); } - test.deepEqual(remoteGlobalIDStrings, ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']); - test.done() - }, - 'should set each PBXContainerItemProxy`s remoteInfo correctly': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - pbxContainerItemProxySection = proj.hash.project.objects['PBXContainerItemProxy'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target, - remoteInfoArray = []; + assert.deepEqual(remoteGlobalIDStrings, ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']); + }); + + it('should set each PBXContainerItemProxy`s remoteInfo correctly', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const pbxContainerItemProxySection = proj.hash.project.objects.PBXContainerItemProxy; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + const remoteInfoArray = []; - for (var index = 0; index < target.dependencies.length; index++) { - var dependency = target.dependencies[index].value, - targetProxy = pbxTargetDependencySection[dependency]['targetProxy']; + for (let index = 0; index < target.dependencies.length; index++) { + const dependency = target.dependencies[index].value; + const targetProxy = pbxTargetDependencySection[dependency].targetProxy; - remoteInfoArray.push(pbxContainerItemProxySection[targetProxy]['remoteInfo']); + remoteInfoArray.push(pbxContainerItemProxySection[targetProxy].remoteInfo); } - test.deepEqual(remoteInfoArray, ['"KitchenSinktablet"', '"TestApp"']); - test.done() - }, - 'should set each PBXContainerItemProxy`s containerPortal correctly': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - pbxContainerItemProxySection = proj.hash.project.objects['PBXContainerItemProxy'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + assert.deepEqual(remoteInfoArray, ['"KitchenSinktablet"', '"TestApp"']); + }); - for (var index = 0; index < target.dependencies.length; index++) { - var dependency = target.dependencies[index].value, - targetProxy = pbxTargetDependencySection[dependency]['targetProxy']; + it('should set each PBXContainerItemProxy`s containerPortal correctly', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const pbxContainerItemProxySection = proj.hash.project.objects.PBXContainerItemProxy; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - test.equal(pbxContainerItemProxySection[targetProxy]['containerPortal'], proj.hash.project['rootObject']); + for (let index = 0; index < target.dependencies.length; index++) { + const dependency = target.dependencies[index].value; + const targetProxy = pbxTargetDependencySection[dependency].targetProxy; + + assert.equal(pbxContainerItemProxySection[targetProxy].containerPortal, proj.hash.project.rootObject); } + }); - test.done() - }, - 'should set each PBXContainerItemProxy`s containerPortal_comment correctly': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - pbxContainerItemProxySection = proj.hash.project.objects['PBXContainerItemProxy'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + it('should set each PBXContainerItemProxy`s containerPortal_comment correctly', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const pbxContainerItemProxySection = proj.hash.project.objects.PBXContainerItemProxy; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - for (var index = 0; index < target.dependencies.length; index++) { - var dependency = target.dependencies[index].value, - targetProxy = pbxTargetDependencySection[dependency]['targetProxy']; + for (let index = 0; index < target.dependencies.length; index++) { + const dependency = target.dependencies[index].value; + const targetProxy = pbxTargetDependencySection[dependency].targetProxy; - test.equal(pbxContainerItemProxySection[targetProxy]['containerPortal_comment'], proj.hash.project['rootObject_comment']); + assert.equal(pbxContainerItemProxySection[targetProxy].containerPortal_comment, proj.hash.project.rootObject_comment); } + }); - test.done() - }, - 'should set each PBXContainerItemProxy`s proxyType correctly': function (test) { - var pbxTargetDependencySection = proj.hash.project.objects['PBXTargetDependency'], - pbxContainerItemProxySection = proj.hash.project.objects['PBXContainerItemProxy'], - target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; + it('should set each PBXContainerItemProxy`s proxyType correctly', () => { + const pbxTargetDependencySection = proj.hash.project.objects.PBXTargetDependency; + const pbxContainerItemProxySection = proj.hash.project.objects.PBXContainerItemProxy; + const target = proj.addTargetDependency('1D6058900D05DD3D006BFB55', ['1D6058900D05DD3D006BFB54', '1D6058900D05DD3D006BFB55']).target; - for (var index = 0; index < target.dependencies.length; index++) { - var dependency = target.dependencies[index].value, - targetProxy = pbxTargetDependencySection[dependency]['targetProxy']; + for (let index = 0; index < target.dependencies.length; index++) { + const dependency = target.dependencies[index].value; + const targetProxy = pbxTargetDependencySection[dependency].targetProxy; - test.equal(pbxContainerItemProxySection[targetProxy]['proxyType'], 1); + assert.equal(pbxContainerItemProxySection[targetProxy].proxyType, 1); } - - test.done() - } -} + }); +}); diff --git a/test/addToPbxFileReferenceSection.js b/test/addToPbxFileReferenceSection.js index d69abbc1..683e675b 100644 --- a/test/addToPbxFileReferenceSection.js +++ b/test/addToPbxFileReferenceSection.js @@ -1,79 +1,82 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var jsonProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(jsonProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - myProj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const jsonProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(jsonProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const myProj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - myProj.hash = cleanHash(); - callback(); -} +describe('addToPbxFileReferenceSection function', () => { + beforeEach(() => { + myProj.hash = cleanHash(); + }); -exports['addToPbxFileReferenceSection function'] = { - 'should add file and comment to fileReferenceSection': function (test) { - var file = new pbxFile('file.m'); + it('should add file and comment to fileReferenceSection', () => { + const file = new PBXFile('file.m'); file.fileRef = myProj.generateUuid(); - myProj.addToPbxFileReferenceSection(file) - - test.equal(myProj.pbxFileReferenceSection()[file.fileRef].isa, 'PBXFileReference'); - test.equal(myProj.pbxFileReferenceSection()[file.fileRef].lastKnownFileType, 'sourcecode.c.objc'); - test.equal(myProj.pbxFileReferenceSection()[file.fileRef].name, '"file.m"'); - test.equal(myProj.pbxFileReferenceSection()[file.fileRef].path, '"file.m"'); - test.equal(myProj.pbxFileReferenceSection()[file.fileRef].sourceTree, '""'); - test.equal(myProj.pbxFileReferenceSection()[file.fileRef].fileEncoding, 4); - test.equal(myProj.pbxFileReferenceSection()[file.fileRef + "_comment"], 'file.m'); - test.done(); - }, - 'should add file with preset explicitFileType to fileReferenceSection correctly': function (test) { - var appexFile = { fileRef: myProj.generateUuid(), isa: 'PBXFileReference', explicitFileType: '"wrapper.app-extension"', path: "WatchKit Extension.appex"}; - - myProj.addToPbxFileReferenceSection(appexFile) - - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].isa, 'PBXFileReference'); - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].explicitFileType, '"wrapper.app-extension"'); - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].path, '"WatchKit Extension.appex"'); - test.done(); - }, - 'should add file with preset includeInIndex to fileReferenceSection correctly': function (test) { - var appexFile = { fileRef: myProj.generateUuid(), isa: 'PBXFileReference', includeInIndex: 0, path: "WatchKit Extension.appex"}; - - myProj.addToPbxFileReferenceSection(appexFile) - - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].isa, 'PBXFileReference'); - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].includeInIndex, 0); - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].path, '"WatchKit Extension.appex"'); - test.done(); - }, - 'should add file with preset sourceTree to fileReferenceSection correctly': function (test) { - var appexFile = { fileRef: myProj.generateUuid(), isa: 'PBXFileReference', sourceTree: 'BUILT_PRODUCTS_DIR', path: "WatchKit Extension.appex"}; - - myProj.addToPbxFileReferenceSection(appexFile) - - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].isa, 'PBXFileReference'); - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].sourceTree, 'BUILT_PRODUCTS_DIR'); - test.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].path, '"WatchKit Extension.appex"'); - test.done(); - } -} + myProj.addToPbxFileReferenceSection(file); + + assert.equal(myProj.pbxFileReferenceSection()[file.fileRef].isa, 'PBXFileReference'); + assert.equal(myProj.pbxFileReferenceSection()[file.fileRef].lastKnownFileType, 'sourcecode.c.objc'); + assert.equal(myProj.pbxFileReferenceSection()[file.fileRef].name, '"file.m"'); + assert.equal(myProj.pbxFileReferenceSection()[file.fileRef].path, '"file.m"'); + assert.equal(myProj.pbxFileReferenceSection()[file.fileRef].sourceTree, '""'); + assert.equal(myProj.pbxFileReferenceSection()[file.fileRef].fileEncoding, 4); + assert.equal(myProj.pbxFileReferenceSection()[file.fileRef + '_comment'], 'file.m'); + }); + + it('should add file with preset explicitFileType to fileReferenceSection correctly', () => { + const appexFile = { fileRef: myProj.generateUuid(), isa: 'PBXFileReference', explicitFileType: '"wrapper.app-extension"', path: 'WatchKit Extension.appex' }; + + myProj.addToPbxFileReferenceSection(appexFile); + + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].isa, 'PBXFileReference'); + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].explicitFileType, '"wrapper.app-extension"'); + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].path, '"WatchKit Extension.appex"'); + }); + + it('should add file with preset includeInIndex to fileReferenceSection correctly', () => { + const appexFile = { fileRef: myProj.generateUuid(), isa: 'PBXFileReference', includeInIndex: 0, path: 'WatchKit Extension.appex' }; + + myProj.addToPbxFileReferenceSection(appexFile); + + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].isa, 'PBXFileReference'); + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].includeInIndex, 0); + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].path, '"WatchKit Extension.appex"'); + }); + + it('should add file with preset sourceTree to fileReferenceSection correctly', () => { + const appexFile = { fileRef: myProj.generateUuid(), isa: 'PBXFileReference', sourceTree: 'BUILT_PRODUCTS_DIR', path: 'WatchKit Extension.appex' }; + + myProj.addToPbxFileReferenceSection(appexFile); + + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].isa, 'PBXFileReference'); + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].sourceTree, 'BUILT_PRODUCTS_DIR'); + assert.equal(myProj.pbxFileReferenceSection()[appexFile.fileRef].path, '"WatchKit Extension.appex"'); + }); +}); diff --git a/test/addWatch2App.js b/test/addWatch2App.js index 2dd72f59..8baf046a 100644 --- a/test/addWatch2App.js +++ b/test/addWatch2App.js @@ -1,165 +1,161 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -var TARGET_NAME = 'TestWatchApp', - TARGET_TYPE = 'watch2_app', - TARGET_SUBFOLDER_NAME = 'TestWatchAppFiles'; - -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addWatchApp = { - 'should create a new watch2 app target with the correct product type': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp2"'); - - test.done(); - }, - 'should create a new watch2 app target with the correct product type, without needing a subfolder name': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp2"'); - - test.done(); - }, - 'should create a new watch2 app target and add source, framework, resource and header files and the corresponding build phases': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME), - options = { 'target' : target.uuid }; - - var sourceFile = proj.addSourceFile('Plugins/file.m', options), - sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid), - resourceFile = proj.addResourceFile('assets.bundle', options), - resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid), - frameworkFile = proj.addFramework('libsqlite3.dylib', options); - frameworkPhase = proj.addBuildPhase([], 'PBXFrameworkBuildPhase', 'Frameworks', target.uuid), - headerFile = proj.addHeaderFile('file.h', options); - - test.ok(sourcePhase); - test.ok(resourcePhase); - test.ok(frameworkPhase); - - test.equal(sourceFile.constructor, pbxFile); - test.equal(resourceFile.constructor, pbxFile); - test.equal(frameworkFile.constructor, pbxFile); - test.equal(headerFile.constructor, pbxFile); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.done(); - }, - 'should create a new watch2 app target and add watch build phase': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp2"'); - - var buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Watch Content', target.uuid); - - test.ok(buildPhase); - test.ok(buildPhase.files); - test.equal(buildPhase.files.length, 1); - test.ok(buildPhase.dstPath); - test.equal(buildPhase.dstPath, '"$(CONTENTS_FOLDER_PATH)/Watch"'); - test.equal(buildPhase.dstSubfolderSpec, 16); - - test.done(); - }, - 'should create a new watch2 app with appropriate target extension': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - - var buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Watch Content', target.uuid) - - var buildPhaseFile = buildPhase.files[0]; - test.ok(buildPhaseFile.value); - var buildPhaseFileSection = proj.pbxBuildFileSection()[buildPhaseFile.value]; - test.ok(buildPhaseFileSection); - test.ok(buildPhaseFileSection.fileRef); - - var buildPhaseFileRef = proj.pbxFileReferenceSection()[buildPhaseFileSection.fileRef]; - test.ok(buildPhaseFileRef); - test.ok(buildPhaseFileRef.name); - test.ok(buildPhaseFileRef.path); - - var quotedTargetPath = "\"" + TARGET_NAME + ".app\""; - test.equal(buildPhaseFileRef.name, quotedTargetPath); - test.equal(buildPhaseFileRef.path, quotedTargetPath); - - test.done(); - } -} +const TARGET_NAME = 'TestWatchApp'; +const TARGET_TYPE = 'watch2_app'; +const TARGET_SUBFOLDER_NAME = 'TestWatchAppFiles'; + +describe('addWatchApp', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + it('should create a new watch2 app target with the correct product type', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + + assert.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp2"'); + }); + + it('should create a new watch2 app target with the correct product type, without needing a subfolder name', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + + assert.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp2"'); + }); + + it('should create a new watch2 app target and add source, framework, resource and header files and the corresponding build phases', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + const options = { target: target.uuid }; + + const sourceFile = proj.addSourceFile('Plugins/file.m', options); + const sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid); + const resourceFile = proj.addResourceFile('assets.bundle', options); + const resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid); + const frameworkFile = proj.addFramework('libsqlite3.dylib', options); + const frameworkPhase = proj.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', target.uuid); + const headerFile = proj.addHeaderFile('file.h', options); + + assert.ok(sourcePhase); + assert.ok(resourcePhase); + assert.ok(frameworkPhase); + + assert.equal(sourceFile.constructor, PBXFile); + assert.equal(resourceFile.constructor, PBXFile); + assert.equal(frameworkFile.constructor, PBXFile); + assert.equal(headerFile.constructor, PBXFile); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + }); + + it('should create a new watch2 app target and add watch build phase', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + + assert.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp2"'); + + const buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Watch Content', target.uuid); + + assert.ok(buildPhase); + assert.ok(buildPhase.files); + assert.equal(buildPhase.files.length, 1); + assert.ok(buildPhase.dstPath); + assert.equal(buildPhase.dstPath, '"$(CONTENTS_FOLDER_PATH)/Watch"'); + assert.equal(buildPhase.dstSubfolderSpec, 16); + }); + + it('should create a new watch2 app with appropriate target extension', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + + const buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed Watch Content', target.uuid); + + const buildPhaseFile = buildPhase.files[0]; + assert.ok(buildPhaseFile.value); + const buildPhaseFileSection = proj.pbxBuildFileSection()[buildPhaseFile.value]; + assert.ok(buildPhaseFileSection); + assert.ok(buildPhaseFileSection.fileRef); + + const buildPhaseFileRef = proj.pbxFileReferenceSection()[buildPhaseFileSection.fileRef]; + assert.ok(buildPhaseFileRef); + assert.ok(buildPhaseFileRef.name); + assert.ok(buildPhaseFileRef.path); + + const quotedTargetPath = '"' + TARGET_NAME + '.app"'; + assert.equal(buildPhaseFileRef.name, quotedTargetPath); + assert.equal(buildPhaseFileRef.path, quotedTargetPath); + }); +}); diff --git a/test/addWatch2Extension.js b/test/addWatch2Extension.js index 302b7526..61a2ce58 100644 --- a/test/addWatch2Extension.js +++ b/test/addWatch2Extension.js @@ -1,187 +1,181 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -var TARGET_NAME = 'TestWatchExtension', - TARGET_TYPE = 'watch2_extension', - TARGET_SUBFOLDER_NAME = 'TestWatchExtensionFiles'; - -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addWatchExtension = { - 'should create a new watch2 extension target with the correct product type': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - test.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.watchkit2-extension"'); - - test.done(); - }, - 'should create a new watch2 extension target and add source, framework, resource and header files and the corresponding build phases': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME), - options = { 'target' : target.uuid }; - - var sourceFile = proj.addSourceFile('Plugins/file.m', options), - sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid), - resourceFile = proj.addResourceFile('assets.bundle', options), - resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid), - frameworkFile = proj.addFramework('libsqlite3.dylib', options); - frameworkPhase = proj.addBuildPhase([], 'PBXFrameworkBuildPhase', 'Frameworks', target.uuid), - headerFile = proj.addHeaderFile('file.h', options); - - test.ok(sourcePhase); - test.ok(resourcePhase); - test.ok(frameworkPhase); - - test.equal(sourceFile.constructor, pbxFile); - test.equal(resourceFile.constructor, pbxFile); - test.equal(frameworkFile.constructor, pbxFile); - test.equal(headerFile.constructor, pbxFile); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.done(); - }, - 'should not create a new watch2 extension build phase if no watch2 app exists': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - var buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed App Extensions', target.uuid) - - test.ok(!buildPhase); - - test.done(); - }, - 'should create a new watch2 extension build phase if watch2 app exists': function (test) { +const TARGET_NAME = 'TestWatchExtension'; +const TARGET_TYPE = 'watch2_extension'; +const TARGET_SUBFOLDER_NAME = 'TestWatchExtensionFiles'; + +describe('addWatchExtension', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + it('should create a new watch2 extension target with the correct product type', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + assert.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.watchkit2-extension"'); + }); + + it('should create a new watch2 extension target and add source, framework, resource and header files and the corresponding build phases', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + const options = { target: target.uuid }; + + const sourceFile = proj.addSourceFile('Plugins/file.m', options); + const sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid); + const resourceFile = proj.addResourceFile('assets.bundle', options); + const resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid); + const frameworkFile = proj.addFramework('libsqlite3.dylib', options); + const frameworkPhase = proj.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', target.uuid); + const headerFile = proj.addHeaderFile('file.h', options); + + assert.ok(sourcePhase); + assert.ok(resourcePhase); + assert.ok(frameworkPhase); + + assert.equal(sourceFile.constructor, PBXFile); + assert.equal(resourceFile.constructor, PBXFile); + assert.equal(frameworkFile.constructor, PBXFile); + assert.equal(headerFile.constructor, PBXFile); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + }); + + it('should not create a new watch2 extension build phase if no watch2 app exists', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + + const buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed App Extensions', target.uuid); + + assert.ok(!buildPhase); + }); + + it('should create a new watch2 extension build phase if watch2 app exists', () => { proj.addTarget('TestWatchApp', 'watch2_app'); - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - var buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed App Extensions', target.uuid) + const buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed App Extensions', target.uuid); - test.ok(buildPhase); - test.ok(buildPhase.files); - test.equal(buildPhase.files.length, 1); - test.ok(buildPhase.dstPath); - test.equal(buildPhase.dstSubfolderSpec, 13); + assert.ok(buildPhase); + assert.ok(buildPhase.files); + assert.equal(buildPhase.files.length, 1); + assert.ok(buildPhase.dstPath); + assert.equal(buildPhase.dstSubfolderSpec, 13); + }); - test.done(); - }, - 'should create a new watch2 extension and add to existing watch2 app build phase and dependency': function (test) { - var watchApp = proj.addTarget('TestWatchApp', 'watch2_app'); + it('should create a new watch2 extension and add to existing watch2 app build phase and dependency', () => { + const watchApp = proj.addTarget('TestWatchApp', 'watch2_app'); - var nativeTargets = proj.pbxNativeTargetSection(); + const nativeTargets = proj.pbxNativeTargetSection(); - test.equal(nativeTargets[watchApp.uuid].buildPhases.length, 0); - test.equal(nativeTargets[watchApp.uuid].dependencies.length, 0); + assert.equal(nativeTargets[watchApp.uuid].buildPhases.length, 0); + assert.equal(nativeTargets[watchApp.uuid].dependencies.length, 0); proj.addTarget(TARGET_NAME, TARGET_TYPE); - test.equal(nativeTargets[watchApp.uuid].buildPhases.length, 1); - test.equal(nativeTargets[watchApp.uuid].dependencies.length, 1); + assert.equal(nativeTargets[watchApp.uuid].buildPhases.length, 1); + assert.equal(nativeTargets[watchApp.uuid].dependencies.length, 1); + }); - test.done(); - }, - 'should not modify watch2 target unless adding watch2 extension': function (test) { - var watchApp = proj.addTarget('TestWatchApp', 'watch2_app'); + it('should not modify watch2 target unless adding watch2 extension', () => { + const watchApp = proj.addTarget('TestWatchApp', 'watch2_app'); - var nativeTargets = proj.pbxNativeTargetSection(); + const nativeTargets = proj.pbxNativeTargetSection(); - test.equal(nativeTargets[watchApp.uuid].buildPhases.length, 0); - test.equal(nativeTargets[watchApp.uuid].dependencies.length, 0); + assert.equal(nativeTargets[watchApp.uuid].buildPhases.length, 0); + assert.equal(nativeTargets[watchApp.uuid].dependencies.length, 0); - proj.addTarget(TARGET_NAME, "app_extension"); + proj.addTarget(TARGET_NAME, 'app_extension'); - test.equal(nativeTargets[watchApp.uuid].buildPhases.length, 0); - test.equal(nativeTargets[watchApp.uuid].dependencies.length, 0); + assert.equal(nativeTargets[watchApp.uuid].buildPhases.length, 0); + assert.equal(nativeTargets[watchApp.uuid].dependencies.length, 0); - proj.addTarget(TARGET_NAME, "watch_extension"); + proj.addTarget(TARGET_NAME, 'watch_extension'); - test.equal(nativeTargets[watchApp.uuid].buildPhases.length, 0); - test.equal(nativeTargets[watchApp.uuid].dependencies.length, 0); + assert.equal(nativeTargets[watchApp.uuid].buildPhases.length, 0); + assert.equal(nativeTargets[watchApp.uuid].dependencies.length, 0); + }); - test.done(); - }, - 'should create a new watch2 extension with appropriate target extension': function (test) { + it('should create a new watch2 extension with appropriate target extension', () => { proj.addTarget('TestWatchApp', 'watch2_app'); - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - - var buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed App Extensions', target.uuid) - - var buildPhaseFile = buildPhase.files[0]; - test.ok(buildPhaseFile.value); - var buildPhaseFileSection = proj.pbxBuildFileSection()[buildPhaseFile.value]; - test.ok(buildPhaseFileSection); - test.ok(buildPhaseFileSection.fileRef); - - var buildPhaseFileRef = proj.pbxFileReferenceSection()[buildPhaseFileSection.fileRef]; - test.ok(buildPhaseFileRef); - test.ok(buildPhaseFileRef.name); - test.ok(buildPhaseFileRef.path); - - var quotedTargetPath = "\"" + TARGET_NAME + ".appex\""; - test.equal(buildPhaseFileRef.name, quotedTargetPath); - test.equal(buildPhaseFileRef.path, quotedTargetPath); - - test.done(); - } -} + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + + const buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed App Extensions', target.uuid); + + const buildPhaseFile = buildPhase.files[0]; + assert.ok(buildPhaseFile.value); + const buildPhaseFileSection = proj.pbxBuildFileSection()[buildPhaseFile.value]; + assert.ok(buildPhaseFileSection); + assert.ok(buildPhaseFileSection.fileRef); + + const buildPhaseFileRef = proj.pbxFileReferenceSection()[buildPhaseFileSection.fileRef]; + assert.ok(buildPhaseFileRef); + assert.ok(buildPhaseFileRef.name); + assert.ok(buildPhaseFileRef.path); + + const quotedTargetPath = '"' + TARGET_NAME + '.appex"'; + assert.equal(buildPhaseFileRef.name, quotedTargetPath); + assert.equal(buildPhaseFileRef.path, quotedTargetPath); + }); +}); diff --git a/test/addWatchApp.js b/test/addWatchApp.js index b1b603d3..47a69a99 100644 --- a/test/addWatchApp.js +++ b/test/addWatchApp.js @@ -1,114 +1,112 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -var TARGET_NAME = 'TestWatchApp', - TARGET_TYPE = 'watch_app', - TARGET_SUBFOLDER_NAME = 'TestWatchAppFiles'; - -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addWatchApp = { - 'should create a new watch app target with the correct product type': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp"'); - - test.done(); - }, - 'should create a new watch app target with the correct product type, without needing a subfolder name': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp"'); - - test.done(); - }, - 'should create a new watch app target and add source, framework, resource and header files and the corresponding build phases': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME), - options = { 'target' : target.uuid }; - - var sourceFile = proj.addSourceFile('Plugins/file.m', options), - sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid), - resourceFile = proj.addResourceFile('assets.bundle', options), - resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid), - frameworkFile = proj.addFramework('libsqlite3.dylib', options); - frameworkPhase = proj.addBuildPhase([], 'PBXFrameworkBuildPhase', 'Frameworks', target.uuid), - headerFile = proj.addHeaderFile('file.h', options); - - test.ok(sourcePhase); - test.ok(resourcePhase); - test.ok(frameworkPhase); - - test.equal(sourceFile.constructor, pbxFile); - test.equal(resourceFile.constructor, pbxFile); - test.equal(frameworkFile.constructor, pbxFile); - test.equal(headerFile.constructor, pbxFile); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.done(); - } -} +const TARGET_NAME = 'TestWatchApp'; +const TARGET_TYPE = 'watch_app'; +const TARGET_SUBFOLDER_NAME = 'TestWatchAppFiles'; + +describe('addWatchApp', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + it('should create a new watch app target with the correct product type', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + + assert.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp"'); + }); + + it('should create a new watch app target with the correct product type, without needing a subfolder name', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + + assert.equal(target.pbxNativeTarget.productType, '"com.apple.product-type.application.watchapp"'); + }); + + it('should create a new watch app target and add source, framework, resource and header files and the corresponding build phases', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + const options = { target: target.uuid }; + + const sourceFile = proj.addSourceFile('Plugins/file.m', options); + const sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid); + const resourceFile = proj.addResourceFile('assets.bundle', options); + const resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid); + const frameworkFile = proj.addFramework('libsqlite3.dylib', options); + const frameworkPhase = proj.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', target.uuid); + const headerFile = proj.addHeaderFile('file.h', options); + + assert.ok(sourcePhase); + assert.ok(resourcePhase); + assert.ok(frameworkPhase); + + assert.equal(sourceFile.constructor, PBXFile); + assert.equal(resourceFile.constructor, PBXFile); + assert.equal(frameworkFile.constructor, PBXFile); + assert.equal(headerFile.constructor, PBXFile); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + }); +}); diff --git a/test/addWatchExtension.js b/test/addWatchExtension.js index 94104884..c4505198 100644 --- a/test/addWatchExtension.js +++ b/test/addWatchExtension.js @@ -1,114 +1,112 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -var TARGET_NAME = 'TestWatchExtension', - TARGET_TYPE = 'watch_extension', - TARGET_SUBFOLDER_NAME = 'TestWatchExtensionFiles'; - -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addWatchExtension = { - 'should create a new watch extension target': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.done(); - }, - 'should create a new watch extension target and add source, framework, resource and header files and the corresponding build phases': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME), - options = { 'target' : target.uuid }; - - var sourceFile = proj.addSourceFile('Plugins/file.m', options), - sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid), - resourceFile = proj.addResourceFile('assets.bundle', options), - resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid), - frameworkFile = proj.addFramework('libsqlite3.dylib', options); - frameworkPhase = proj.addBuildPhase([], 'PBXFrameworkBuildPhase', 'Frameworks', target.uuid), - headerFile = proj.addHeaderFile('file.h', options); - - test.ok(sourcePhase); - test.ok(resourcePhase); - test.ok(frameworkPhase); - - test.equal(sourceFile.constructor, pbxFile); - test.equal(resourceFile.constructor, pbxFile); - test.equal(frameworkFile.constructor, pbxFile); - test.equal(headerFile.constructor, pbxFile); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - test.done(); - }, - 'should not create a new watch extension build phase if no watch app exists': function (test) { - var target = proj.addTarget(TARGET_NAME, TARGET_TYPE); - - test.ok(typeof target == 'object'); - test.ok(target.uuid); - test.ok(target.pbxNativeTarget); - test.ok(target.pbxNativeTarget.isa); - test.ok(target.pbxNativeTarget.name); - test.ok(target.pbxNativeTarget.productName); - test.ok(target.pbxNativeTarget.productReference); - test.ok(target.pbxNativeTarget.productType); - test.ok(target.pbxNativeTarget.buildConfigurationList); - test.ok(target.pbxNativeTarget.buildPhases); - test.ok(target.pbxNativeTarget.buildRules); - test.ok(target.pbxNativeTarget.dependencies); - - var buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed App Extensions', target.uuid) - - test.ok(!buildPhase); - - test.done(); - } -} +const TARGET_NAME = 'TestWatchExtension'; +const TARGET_TYPE = 'watch_extension'; +const TARGET_SUBFOLDER_NAME = 'TestWatchExtensionFiles'; + +describe('addWatchExtension', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + it('should create a new watch extension target', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + }); + + it('should create a new watch extension target and add source, framework, resource and header files and the corresponding build phases', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE, TARGET_SUBFOLDER_NAME); + const options = { target: target.uuid }; + + const sourceFile = proj.addSourceFile('Plugins/file.m', options); + const sourcePhase = proj.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid); + const resourceFile = proj.addResourceFile('assets.bundle', options); + const resourcePhase = proj.addBuildPhase([], 'PBXResourcesBuildPhase', 'Resources', target.uuid); + const frameworkFile = proj.addFramework('libsqlite3.dylib', options); + const frameworkPhase = proj.addBuildPhase([], 'PBXFrameworksBuildPhase', 'Frameworks', target.uuid); + const headerFile = proj.addHeaderFile('file.h', options); + + assert.ok(sourcePhase); + assert.ok(resourcePhase); + assert.ok(frameworkPhase); + + assert.equal(sourceFile.constructor, PBXFile); + assert.equal(resourceFile.constructor, PBXFile); + assert.equal(frameworkFile.constructor, PBXFile); + assert.equal(headerFile.constructor, PBXFile); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + }); + + it('should not create a new watch extension build phase if no watch app exists', () => { + const target = proj.addTarget(TARGET_NAME, TARGET_TYPE); + + assert.ok(typeof target === 'object'); + assert.ok(target.uuid); + assert.ok(target.pbxNativeTarget); + assert.ok(target.pbxNativeTarget.isa); + assert.ok(target.pbxNativeTarget.name); + assert.ok(target.pbxNativeTarget.productName); + assert.ok(target.pbxNativeTarget.productReference); + assert.ok(target.pbxNativeTarget.productType); + assert.ok(target.pbxNativeTarget.buildConfigurationList); + assert.ok(target.pbxNativeTarget.buildPhases); + assert.ok(target.pbxNativeTarget.buildRules); + assert.ok(target.pbxNativeTarget.dependencies); + + const buildPhase = proj.buildPhaseObject('PBXCopyFilesBuildPhase', 'Embed App Extensions', target.uuid); + + assert.ok(!buildPhase); + }); +}); diff --git a/test/addXCConfigurationList.js b/test/addXCConfigurationList.js index 6ef74c31..45cc1cce 100644 --- a/test/addXCConfigurationList.js +++ b/test/addXCConfigurationList.js @@ -1,132 +1,131 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - proj = new pbx('.'), - debugConfiguration = { - isa: 'XCBuildConfiguration', - buildSettings: { - GCC_PREPROCESSOR_DEFINITIONS: [ - '"DEBUG=1"', - '"$(inherited)"', - ], - INFOPLIST_FILE: "Info.Plist", - LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"', - PRODUCT_NAME: '"${TARGET_NAME}"', - SKIP_INSTALL: 'YES' - }, - name: 'Debug' +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); +const debugConfiguration = { + isa: 'XCBuildConfiguration', + buildSettings: { + GCC_PREPROCESSOR_DEFINITIONS: [ + '"DEBUG=1"', + '"$(inherited)"' + ], + INFOPLIST_FILE: 'Info.Plist', + LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"', + PRODUCT_NAME: '"${TARGET_NAME}"', // eslint-disable-line no-template-curly-in-string + SKIP_INSTALL: 'YES' }, - releaseConfiguration = { - isa: 'XCBuildConfiguration', - buildSettings: { - INFOPLIST_FILE: "Info.Plist", - LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"', - PRODUCT_NAME: '"${TARGET_NAME}"', - SKIP_INSTALL: 'YES' - }, - name: 'Release' - }; - -function cleanHash() { + name: 'Debug' +}; +const releaseConfiguration = { + isa: 'XCBuildConfiguration', + buildSettings: { + INFOPLIST_FILE: 'Info.Plist', + LD_RUNPATH_SEARCH_PATHS: '"$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"', + PRODUCT_NAME: '"${TARGET_NAME}"', // eslint-disable-line no-template-curly-in-string + SKIP_INSTALL: 'YES' + }, + name: 'Release' +}; + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('addXCConfigurationList', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + it('should return an XCConfigurationList', () => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj').parseSync(); + const xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); -exports.addXCConfigurationList = { - 'should return an XCConfigurationList': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj').parseSync(), - xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); + assert.ok(typeof xcConfigurationList === 'object'); + }); - test.ok(typeof xcConfigurationList === 'object'); - test.done(); - }, - 'should set a uuid on the XCConfigurationList': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj').parseSync(), - xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); + it('should set a uuid on the XCConfigurationList', () => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj').parseSync(); + const xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); - test.ok(xcConfigurationList.uuid); - test.done(); - }, - 'should add configurations to pbxBuildConfigurationSection': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj').parseSync(), - pbxBuildConfigurationSection = myProj.pbxXCBuildConfigurationSection(), - xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'), - xcConfigurationListConfigurations = xcConfigurationList.xcConfigurationList.buildConfigurations; - - for (var index = 0; index < xcConfigurationListConfigurations.length; index++) { - var configuration = xcConfigurationListConfigurations[index]; - test.ok(pbxBuildConfigurationSection[configuration.value]); + assert.ok(xcConfigurationList.uuid); + }); + + it('should add configurations to pbxBuildConfigurationSection', () => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj').parseSync(); + const pbxBuildConfigurationSection = myProj.pbxXCBuildConfigurationSection(); + const xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); + const xcConfigurationListConfigurations = xcConfigurationList.xcConfigurationList.buildConfigurations; + + for (let index = 0; index < xcConfigurationListConfigurations.length; index++) { + const configuration = xcConfigurationListConfigurations[index]; + assert.ok(pbxBuildConfigurationSection[configuration.value]); } + }); - test.done(); - }, - 'should add XCConfigurationList to pbxXCConfigurationListSection': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj').parseSync(), - pbxXCConfigurationListSection = myProj.pbxXCConfigurationList(); - xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); + it('should add XCConfigurationList to pbxXCConfigurationListSection', () => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj').parseSync(); + const pbxXCConfigurationListSection = myProj.pbxXCConfigurationList(); + const xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); - test.ok(pbxXCConfigurationListSection[xcConfigurationList.uuid]); - test.done(); - }, - 'should add XCConfigurationList object correctly': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj').parseSync(), - pbxXCConfigurationListSection = myProj.pbxXCConfigurationList(); - xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'), - xcConfigurationListInPbx = pbxXCConfigurationListSection[xcConfigurationList.uuid]; - - test.deepEqual(xcConfigurationListInPbx, xcConfigurationList.xcConfigurationList); - test.done(); - }, - 'should add correct configurations to XCConfigurationList and to pbxBuildConfigurationSection': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj').parseSync(), - pbxXCConfigurationListSection = myProj.pbxXCConfigurationList(); - pbxBuildConfigurationSection = myProj.pbxXCBuildConfigurationSection(), - xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'), - xcConfigurationListConfigurations = xcConfigurationList.xcConfigurationList.buildConfigurations, - expectedConfigurations = [], - xcConfigurationListInPbx = pbxXCConfigurationListSection[xcConfigurationList.uuid]; - - for (var index = 0; index < xcConfigurationListConfigurations.length; index++) { - var configuration = xcConfigurationListConfigurations[index]; + assert.ok(pbxXCConfigurationListSection[xcConfigurationList.uuid]); + }); + + it('should add XCConfigurationList object correctly', () => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj').parseSync(); + const pbxXCConfigurationListSection = myProj.pbxXCConfigurationList(); + const xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); + const xcConfigurationListInPbx = pbxXCConfigurationListSection[xcConfigurationList.uuid]; + + assert.deepEqual(xcConfigurationListInPbx, xcConfigurationList.xcConfigurationList); + }); + + it('should add correct configurations to XCConfigurationList and to pbxBuildConfigurationSection', () => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj').parseSync(); + const pbxXCConfigurationListSection = myProj.pbxXCConfigurationList(); + const pbxBuildConfigurationSection = myProj.pbxXCBuildConfigurationSection(); + const xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); + const xcConfigurationListConfigurations = xcConfigurationList.xcConfigurationList.buildConfigurations; + const expectedConfigurations = []; + const xcConfigurationListInPbx = pbxXCConfigurationListSection[xcConfigurationList.uuid]; + + for (let index = 0; index < xcConfigurationListConfigurations.length; index++) { + const configuration = xcConfigurationListConfigurations[index]; expectedConfigurations.push(pbxBuildConfigurationSection[configuration.value]); } - test.deepEqual(expectedConfigurations, [debugConfiguration, releaseConfiguration]); - test.deepEqual(xcConfigurationListInPbx.buildConfigurations, xcConfigurationListConfigurations); - test.done(); - }, - 'should set comments for pbxBuildConfigurations': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj').parseSync(), - pbxBuildConfigurationSection = myProj.pbxXCBuildConfigurationSection(), - xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'), - xcConfigurationListConfigurations = xcConfigurationList.xcConfigurationList.buildConfigurations; - - for (var index = 0; index < xcConfigurationListConfigurations.length; index++) { - var configuration = xcConfigurationListConfigurations[index]; - test.ok(pbxBuildConfigurationSection[configuration.value + '_comment']); - } + assert.deepEqual(expectedConfigurations, [debugConfiguration, releaseConfiguration]); + assert.deepEqual(xcConfigurationListInPbx.buildConfigurations, xcConfigurationListConfigurations); + }); - test.done(); - } -} + it('should set comments for pbxBuildConfigurations', () => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj').parseSync(); + const pbxBuildConfigurationSection = myProj.pbxXCBuildConfigurationSection(); + const xcConfigurationList = myProj.addXCConfigurationList([debugConfiguration, releaseConfiguration], 'Release', 'XCConfigurationList Comment'); + const xcConfigurationListConfigurations = xcConfigurationList.xcConfigurationList.buildConfigurations; + + for (let index = 0; index < xcConfigurationListConfigurations.length; index++) { + const configuration = xcConfigurationListConfigurations[index]; + assert.ok(pbxBuildConfigurationSection[configuration.value + '_comment']); + } + }); +}); diff --git a/test/dataModelDocument.js b/test/dataModelDocument.js index 76477edd..709c84d7 100644 --- a/test/dataModelDocument.js +++ b/test/dataModelDocument.js @@ -1,179 +1,178 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var jsonProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(jsonProject), - path = require('path'), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'), - singleDataModelFilePath = __dirname + '/fixtures/single-data-model.xcdatamodeld', - multipleDataModelFilePath = __dirname + '/fixtures/multiple-data-model.xcdatamodeld'; - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const jsonProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(jsonProject); +const path = require('node:path'); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); +const singleDataModelFilePath = path.join(__dirname, 'fixtures', 'single-data-model.xcdatamodeld'); +const multipleDataModelFilePath = path.join(__dirname, 'fixtures', 'multiple-data-model.xcdatamodeld'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('dataModelDocument', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxFile', () => { + const newFile = proj.addDataModelDocument(singleDataModelFilePath); + + assert.equal(newFile.constructor, PBXFile); + }); + + it('should set a uuid on the pbxFile', () => { + const newFile = proj.addDataModelDocument(singleDataModelFilePath); + + assert.ok(newFile.uuid); + }); + + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addDataModelDocument(singleDataModelFilePath); + + assert.ok(newFile.fileRef); + }); + + it('should set an optional target on the pbxFile', () => { + const target = proj.findTargetKey('TestApp'); + const newFile = proj.addDataModelDocument(singleDataModelFilePath, undefined, { target }); + + assert.equal(newFile.target, target); + }); + + it('should populate the PBXBuildFile section with 2 fields', () => { + const newFile = proj.addDataModelDocument(singleDataModelFilePath); + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; + + assert.equal(59 + 1, bfsLength); + assert.ok(buildFileSection[newFile.uuid]); + assert.ok(buildFileSection[newFile.uuid + '_comment']); + }); + + it('should populate the PBXFileReference section with 2 fields for single model document', () => { + const newFile = proj.addDataModelDocument(singleDataModelFilePath); + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + + assert.equal(66 + 2, frsLength); + assert.ok(fileRefSection[newFile.models[0].fileRef]); + assert.ok(fileRefSection[newFile.models[0].fileRef + '_comment']); + }); + + it('should populate the PBXFileReference section with 2 fields for each model of a model document', () => { + const newFile = proj.addDataModelDocument(multipleDataModelFilePath); + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; + + assert.equal(66 + 2 * 2, frsLength); + assert.ok(fileRefSection[newFile.models[0].fileRef]); + assert.ok(fileRefSection[newFile.models[0].fileRef + '_comment']); + assert.ok(fileRefSection[newFile.models[1].fileRef]); + assert.ok(fileRefSection[newFile.models[1].fileRef + '_comment']); + }); -exports.dataModelDocument = { - 'should return a pbxFile': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath); - - test.equal(newFile.constructor, pbxFile); - test.done() - }, - 'should set a uuid on the pbxFile': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath); - - test.ok(newFile.uuid); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath); - - test.ok(newFile.fileRef); - test.done() - }, - 'should set an optional target on the pbxFile': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath, undefined, { target: target }), - target = proj.findTargetKey('TestApp'); - - test.equal(newFile.target, target); - test.done() - }, - 'should populate the PBXBuildFile section with 2 fields': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; - - test.equal(59 + 1, bfsLength); - test.ok(buildFileSection[newFile.uuid]); - test.ok(buildFileSection[newFile.uuid + '_comment']); - - test.done(); - }, - 'should populate the PBXFileReference section with 2 fields for single model document': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(66 + 2, frsLength); - test.ok(fileRefSection[newFile.models[0].fileRef]); - test.ok(fileRefSection[newFile.models[0].fileRef + '_comment']); - - test.done(); - }, - 'should populate the PBXFileReference section with 2 fields for each model of a model document': function (test) { - var newFile = proj.addDataModelDocument(multipleDataModelFilePath), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(66 + 2 * 2, frsLength); - test.ok(fileRefSection[newFile.models[0].fileRef]); - test.ok(fileRefSection[newFile.models[0].fileRef + '_comment']); - test.ok(fileRefSection[newFile.models[1].fileRef]); - test.ok(fileRefSection[newFile.models[1].fileRef + '_comment']); - - test.done(); - }, - 'should add to resources group by default': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath); - groupChildren = proj.pbxGroupByName('Resources').children, - found = false; - - for (var index in groupChildren) { + it('should add to resources group by default', () => { + proj.addDataModelDocument(singleDataModelFilePath); + const groupChildren = proj.pbxGroupByName('Resources').children; + let found = false; + + for (const index in groupChildren) { if (groupChildren[index].comment === 'single-data-model.xcdatamodeld') { found = true; break; } } - test.ok(found); - test.done(); - }, - 'should add to group specified by key': function (test) { - var group = 'Frameworks', - newFile = proj.addDataModelDocument(singleDataModelFilePath, proj.findPBXGroupKey({ name: group })); - groupChildren = proj.pbxGroupByName(group).children; - - var found = false; - for (var index in groupChildren) { + assert.ok(found); + }); + + it('should add to group specified by key', () => { + const group = 'Frameworks'; + proj.addDataModelDocument(singleDataModelFilePath, proj.findPBXGroupKey({ name: group })); + const groupChildren = proj.pbxGroupByName(group).children; + + let found = false; + for (const index in groupChildren) { if (groupChildren[index].comment === path.basename(singleDataModelFilePath)) { found = true; break; } } - test.ok(found); - test.done(); - }, - 'should add to group specified by name': function (test) { - var group = 'Frameworks', - newFile = proj.addDataModelDocument(singleDataModelFilePath, group); - groupChildren = proj.pbxGroupByName(group).children; - - var found = false; - for (var index in groupChildren) { + assert.ok(found); + }); + + it('should add to group specified by name', () => { + const group = 'Frameworks'; + proj.addDataModelDocument(singleDataModelFilePath, group); + const groupChildren = proj.pbxGroupByName(group).children; + + let found = false; + for (const index in groupChildren) { if (groupChildren[index].comment === path.basename(singleDataModelFilePath)) { found = true; break; } } - test.ok(found); - test.done(); - }, - 'should add to the PBXSourcesBuildPhase': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath), - sources = proj.pbxSourcesBuildPhaseObj(); - - test.equal(sources.files.length, 2 + 1); - test.done(); - }, - 'should create a XCVersionGroup section': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath), - xcVersionGroupSection = proj.xcVersionGroupSection(); - - test.ok(xcVersionGroupSection[newFile.fileRef]); - test.done(); - }, - 'should populate the XCVersionGroup comment correctly': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath), - xcVersionGroupSection = proj.xcVersionGroupSection(), - commentKey = newFile.fileRef + '_comment'; - - test.equal(xcVersionGroupSection[commentKey], path.basename(singleDataModelFilePath)); - test.done(); - }, - 'should add the XCVersionGroup object correctly': function (test) { - var newFile = proj.addDataModelDocument(singleDataModelFilePath), - xcVersionGroupSection = proj.xcVersionGroupSection(), - xcVersionGroupEntry = xcVersionGroupSection[newFile.fileRef]; - - test.equal(xcVersionGroupEntry.isa, 'XCVersionGroup'); - test.equal(xcVersionGroupEntry.children[0], newFile.models[0].fileRef); - test.equal(xcVersionGroupEntry.currentVersion, newFile.currentModel.fileRef); - test.equal(xcVersionGroupEntry.name, path.basename(singleDataModelFilePath)); - // Need to validate against normalized path, since paths should contain forward slash on OSX - test.equal(xcVersionGroupEntry.path, singleDataModelFilePath.replace(/\\/g, '/')); - test.equal(xcVersionGroupEntry.sourceTree, '""'); - test.equal(xcVersionGroupEntry.versionGroupType, 'wrapper.xcdatamodel'); + assert.ok(found); + }); - test.done(); - } -} + it('should add to the PBXSourcesBuildPhase', () => { + proj.addDataModelDocument(singleDataModelFilePath); + const sources = proj.pbxSourcesBuildPhaseObj(); + + assert.equal(sources.files.length, 2 + 1); + }); + + it('should create a XCVersionGroup section', () => { + const newFile = proj.addDataModelDocument(singleDataModelFilePath); + const xcVersionGroupSection = proj.xcVersionGroupSection(); + + assert.ok(xcVersionGroupSection[newFile.fileRef]); + }); + + it('should populate the XCVersionGroup comment correctly', () => { + const newFile = proj.addDataModelDocument(singleDataModelFilePath); + const xcVersionGroupSection = proj.xcVersionGroupSection(); + const commentKey = newFile.fileRef + '_comment'; + + assert.equal(xcVersionGroupSection[commentKey], path.basename(singleDataModelFilePath)); + }); + + it('should add the XCVersionGroup object correctly', () => { + const newFile = proj.addDataModelDocument(singleDataModelFilePath); + const xcVersionGroupSection = proj.xcVersionGroupSection(); + const xcVersionGroupEntry = xcVersionGroupSection[newFile.fileRef]; + + assert.equal(xcVersionGroupEntry.isa, 'XCVersionGroup'); + assert.equal(xcVersionGroupEntry.children[0], newFile.models[0].fileRef); + assert.equal(xcVersionGroupEntry.currentVersion, newFile.currentModel.fileRef); + assert.equal(xcVersionGroupEntry.name, path.basename(singleDataModelFilePath)); + // Need to validate against normalized path, since paths should contain forward slash on OSX + assert.equal(xcVersionGroupEntry.path, singleDataModelFilePath.replace(/\\/g, '/')); + assert.equal(xcVersionGroupEntry.sourceTree, '""'); + assert.equal(xcVersionGroupEntry.versionGroupType, 'wrapper.xcdatamodel'); + }); +}); diff --git a/test/fixtures/multiple-data-model.xcdatamodeld/.xccurrentversion b/test/fixtures/multiple-data-model.xcdatamodeld/.xccurrentversion index cb72aba0..0d7c1611 100644 --- a/test/fixtures/multiple-data-model.xcdatamodeld/.xccurrentversion +++ b/test/fixtures/multiple-data-model.xcdatamodeld/.xccurrentversion @@ -1,4 +1,22 @@ + diff --git a/test/fixtures/multiple-data-model.xcdatamodeld/1.xcdatamodel/contents b/test/fixtures/multiple-data-model.xcdatamodeld/1.xcdatamodel/contents index 6bd3dcd4..d34aec35 100644 --- a/test/fixtures/multiple-data-model.xcdatamodeld/1.xcdatamodel/contents +++ b/test/fixtures/multiple-data-model.xcdatamodeld/1.xcdatamodel/contents @@ -1,4 +1,22 @@ + - \ No newline at end of file + diff --git a/test/fixtures/multiple-data-model.xcdatamodeld/2.xcdatamodel/contents b/test/fixtures/multiple-data-model.xcdatamodeld/2.xcdatamodel/contents index 6bd3dcd4..d34aec35 100644 --- a/test/fixtures/multiple-data-model.xcdatamodeld/2.xcdatamodel/contents +++ b/test/fixtures/multiple-data-model.xcdatamodeld/2.xcdatamodel/contents @@ -1,4 +1,22 @@ + - \ No newline at end of file + diff --git a/test/fixtures/single-data-model.xcdatamodeld/SingleDataModel.xcdatamodel/contents b/test/fixtures/single-data-model.xcdatamodeld/SingleDataModel.xcdatamodel/contents index 6bd3dcd4..d34aec35 100644 --- a/test/fixtures/single-data-model.xcdatamodeld/SingleDataModel.xcdatamodel/contents +++ b/test/fixtures/single-data-model.xcdatamodeld/SingleDataModel.xcdatamodel/contents @@ -1,4 +1,22 @@ + - \ No newline at end of file + diff --git a/test/group.js b/test/group.js index af2454e3..0316f774 100644 --- a/test/group.js +++ b/test/group.js @@ -1,29 +1,33 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - project, - projectHash; - -var findChildInGroup = function(obj, target) { - var found = false; - - for (var i = 0, j = obj.children.length; i < j; i++) { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +let project; + +const findChildInGroup = function (obj, target) { + let found = false; + + for (let i = 0, j = obj.children.length; i < j; i++) { if (obj.children[i].value === target) { found = true; break; @@ -31,12 +35,12 @@ var findChildInGroup = function(obj, target) { } return found; -} +}; -var findFileByUUID = function(obj, target) { - var found = false; +const findFileByUUID = function (obj, target) { + let found = false; - for (var k = 0, l = obj.files.length; k < l; k++) { + for (let k = 0, l = obj.files.length; k < l; k++) { if (obj.files[k].value === target) { found = true; break; @@ -44,12 +48,12 @@ var findFileByUUID = function(obj, target) { } return found; -} +}; -var findByFileRef = function(obj, target) { - var found = false; +const findByFileRef = function (obj, target) { + let found = false; - for (var property in obj) { + for (const property in obj) { if (!/comment/.test(property)) { if (obj[property].fileRef === target) { found = true; @@ -58,419 +62,395 @@ var findByFileRef = function(obj, target) { } } return found; -} +}; -var findByName = function(obj, target) { - var found = false; - for (var property in obj) { +const findByName = function (obj, target) { + let found = false; + for (const property in obj) { if (!/comment/.test(property)) { - var value = obj[property]; + const value = obj[property]; if (value.name === target) { found = true; } } } return found; -} - -exports.setUp = function(callback) { - project = new pbx('test/parser/projects/group.pbxproj'); - projectHash = project.parseSync(); - callback(); -} - -exports.getGroupByKey = { - 'should return PBXGroup for Classes': function(test) { - var groupKey = project.findPBXGroupKey({name: 'Classes'}); - var group = project.getPBXGroupByKey(groupKey); - test.ok(group.name === 'Classes'); - test.done(); - }, - 'should return PBXGroup for Plugins': function(test) { - var groupKey = project.findPBXGroupKey({name: 'Plugins'}); - var group = project.getPBXGroupByKey(groupKey); - test.ok(group.name === 'Plugins'); - test.done(); - } -} - -exports.createGroup = { - 'should create a new Test Group': function(test) { - var found = false; - var groups = project.getPBXObject('PBXGroup'); - - var found = findByName(groups, 'Test'); - test.ok(found === false); - - - var group = project.findPBXGroupKey({name:'Test'}); - test.ok(group === undefined); - - project.pbxCreateGroup('Test', 'Test'); - - groups = project.getPBXObject('PBXGroup'); - found = findByName(groups, 'Test'); - test.ok(found === true); - - group = project.findPBXGroupKey({name:'Test'}); - test.ok(typeof group === 'string'); - test.done(); - } -} - -exports.findGroupKey = { - 'should return a valid group key':function(test) { - var keyByName = project.findPBXGroupKey({ name: 'Classes'}); - var keyByPath = project.findPBXGroupKey({ path: 'icons'}); - var keyByPathName = project.findPBXGroupKey({ path: '"HelloCordova/Plugins"', name: 'Plugins'}); - var nonExistingKey = project.findPBXGroupKey({ name: 'Foo'}); - - test.ok(keyByName === '080E96DDFE201D6D7F000001'); - test.ok(keyByPath === '308D052D1370CCF300D202BF'); - test.ok(keyByPathName === '307C750510C5A3420062BCA9'); - test.ok(nonExistingKey === undefined); - - test.done(); - } -} - -exports.addGroupToGroup = { - 'should create a new test group then add group to Classes group': function(test) { - var testKey = project.pbxCreateGroup('Test', 'Test'); - var classesKey = project.findPBXGroupKey({name: 'Classes'}); - project.addToPbxGroup(testKey, classesKey); - - var classesGroup = project.getPBXGroupByKey(classesKey); - var foundTestGroup = false; - for (var i = 0, j = classesGroup.children.length; i < j; i++) { - var child = classesGroup.children[i]; - if (child.value === testKey && child.comment === 'Test') { - foundTestGroup = true; - } - } - - test.ok(foundTestGroup); - - test.done(); - } -} - -exports.predefinedPbxGroups = { - setUp: function(callback) { - project = new pbx('test/parser/projects/empty-groups.pbxproj').parseSync(); - - this.file = new pbxFile('some-file.m'); - this.file.fileRef = project.generateUuid(); - project.addToPbxFileReferenceSection(this.file); - - callback(); - }, - - 'should add a file to "Plugins" group': function(test) { - project.addToPluginsPbxGroup(this.file); - var foundInGroup = findChildInGroup(project.pbxGroupByName('Plugins'), this.file.fileRef); - test.ok(foundInGroup); - test.done(); - }, - - 'should remove a file from "Plugins" group': function(test) { - project.addToPluginsPbxGroup(this.file); - project.removeFromPluginsPbxGroup(this.file); - - var foundInGroup = findChildInGroup(project.pbxGroupByName('Plugins'), this.file.fileRef); - test.ok(!foundInGroup); - test.done(); - }, - - 'should add a file to "Resources" group': function(test) { - project.addToResourcesPbxGroup(this.file); - - var foundInGroup = findChildInGroup(project.pbxGroupByName('Resources'), this.file.fileRef); - test.ok(foundInGroup); - test.done(); - }, - - 'should remove a file from "Resources" group': function(test) { - project.addToResourcesPbxGroup(this.file); - project.removeFromResourcesPbxGroup(this.file); - - var foundInGroup = findChildInGroup(project.pbxGroupByName('Resources'), this.file.fileRef); - test.ok(!foundInGroup); - test.done(); - }, - - 'should add a file to "Frameworks" group': function(test) { - project.addToFrameworksPbxGroup(this.file); - - var foundInGroup = findChildInGroup(project.pbxGroupByName('Frameworks'), this.file.fileRef); - test.ok(foundInGroup); - test.done(); - }, - - 'should remove a file from "Frameworks" group': function(test) { - project.addToFrameworksPbxGroup(this.file); - project.removeFromFrameworksPbxGroup(this.file); - - var foundInGroup = findChildInGroup(project.pbxGroupByName('Frameworks'), this.file.fileRef); - test.ok(!foundInGroup); - test.done(); - }, - - 'should add a file to "Products" group': function(test) { - project.addToProductsPbxGroup(this.file); - - var foundInGroup = findChildInGroup(project.pbxGroupByName('Products'), this.file.fileRef); - test.ok(foundInGroup); - test.done(); - }, - - 'should remove a file from "Products" group': function(test) { - project.addToProductsPbxGroup(this.file); - project.removeFromProductsPbxGroup(this.file); - - var foundInGroup = findChildInGroup(project.pbxGroupByName('Products'), this.file.fileRef); - test.ok(!foundInGroup); - test.done(); - } }; -exports.addSourceFileToGroup = { - 'should create group + add source file' : function(test) { - var testKey = project.pbxCreateGroup('Test', 'Test'); - var file = project.addSourceFile('Notifications.m', {}, testKey); - - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(foundInGroup); - - var foundInBuildFileSection = findByFileRef(project.pbxBuildFileSection(), file.fileRef); - test.ok(foundInBuildFileSection); - - var foundInBuildPhase = findFileByUUID(project.pbxSourcesBuildPhaseObj(), file.uuid); - test.ok(foundInBuildPhase); - - test.done(); - } -} - -exports.removeSourceFileFromGroup = { - 'should create group + add source file then remove source file' : function(test) { - var testKey = project.pbxCreateGroup('Test', 'Test'); - var file = project.addSourceFile('Notifications.m', {}, testKey); - - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(foundInGroup); - - var foundInBuildFileSection = findByFileRef(project.pbxBuildFileSection(), file.fileRef); - test.ok(foundInBuildFileSection); - - var foundInBuildPhase = findFileByUUID(project.pbxSourcesBuildPhaseObj(), file.uuid); - test.ok(foundInBuildPhase); - - project.removeSourceFile('Notifications.m', {}, testKey); - - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(!foundInGroup); - - var foundInBuildFileSection = findByFileRef(project.pbxBuildFileSection(), file.fileRef); - test.ok(!foundInBuildFileSection); - - var foundInBuildPhase = findFileByUUID(project.pbxSourcesBuildPhaseObj(), file.uuid); - test.ok(!foundInBuildPhase); - - test.done(); - } -} - -exports.addHeaderFileToGroup = { - 'should create group + add header file' : function(test) { - var testKey = project.pbxCreateGroup('Test', 'Test'); - var file = project.addHeaderFile('Notifications.h', {}, testKey); - - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(foundInGroup); +describe('group', () => { + beforeEach(() => { + project = new PBXProject('test/parser/projects/group.pbxproj'); + project.parseSync(); + }); + + describe('getGroupByKey', () => { + it('should return PBXGroup for Classes', () => { + const groupKey = project.findPBXGroupKey({ name: 'Classes' }); + const group = project.getPBXGroupByKey(groupKey); + assert.ok(group.name === 'Classes'); + }); + + it('should return PBXGroup for Plugins', () => { + const groupKey = project.findPBXGroupKey({ name: 'Plugins' }); + const group = project.getPBXGroupByKey(groupKey); + assert.ok(group.name === 'Plugins'); + }); + }); + + describe('createGroup', () => { + it('should create a new Test Group', () => { + let found = false; + let groups = project.getPBXObject('PBXGroup'); + + found = findByName(groups, 'Test'); + assert.ok(found === false); + + let group = project.findPBXGroupKey({ name: 'Test' }); + assert.ok(group === undefined); + + project.pbxCreateGroup('Test', 'Test'); + + groups = project.getPBXObject('PBXGroup'); + found = findByName(groups, 'Test'); + assert.ok(found === true); + + group = project.findPBXGroupKey({ name: 'Test' }); + assert.ok(typeof group === 'string'); + }); + }); + + describe('findGroupKey', () => { + it('should return a valid group key', () => { + const keyByName = project.findPBXGroupKey({ name: 'Classes' }); + const keyByPath = project.findPBXGroupKey({ path: 'icons' }); + const keyByPathName = project.findPBXGroupKey({ path: '"HelloCordova/Plugins"', name: 'Plugins' }); + const nonExistingKey = project.findPBXGroupKey({ name: 'Foo' }); + + assert.ok(keyByName === '080E96DDFE201D6D7F000001'); + assert.ok(keyByPath === '308D052D1370CCF300D202BF'); + assert.ok(keyByPathName === '307C750510C5A3420062BCA9'); + assert.ok(nonExistingKey === undefined); + }); + }); + + describe('addGroupToGroup', () => { + it('should create a new test group then add group to Classes group', () => { + const testKey = project.pbxCreateGroup('Test', 'Test'); + const classesKey = project.findPBXGroupKey({ name: 'Classes' }); + project.addToPbxGroup(testKey, classesKey); + + const classesGroup = project.getPBXGroupByKey(classesKey); + let foundTestGroup = false; + for (let i = 0, j = classesGroup.children.length; i < j; i++) { + const child = classesGroup.children[i]; + if (child.value === testKey && child.comment === 'Test') { + foundTestGroup = true; + } + } - test.done(); - } -} + assert.ok(foundTestGroup); + }); + }); -exports.removeHeaderFileFromGroup = { - 'should create group + add source file then remove header file' : function(test) { - var testKey = project.pbxCreateGroup('Test', 'Test'); - var file = project.addHeaderFile('Notifications.h', {}, testKey); + describe('predefinedPbxGroups', () => { + beforeEach(() => { + project = new PBXProject('test/parser/projects/empty-groups.pbxproj').parseSync(); - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(foundInGroup); + this.file = new PBXFile('some-file.m'); + this.file.fileRef = project.generateUuid(); + project.addToPbxFileReferenceSection(this.file); + }); - project.removeHeaderFile('Notifications.h', {}, testKey); + it('should add a file to "Plugins" group', () => { + project.addToPluginsPbxGroup(this.file); + const foundInGroup = findChildInGroup(project.pbxGroupByName('Plugins'), this.file.fileRef); + assert.ok(foundInGroup); + }); - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(!foundInGroup); + it('should remove a file from "Plugins" group', () => { + project.addToPluginsPbxGroup(this.file); + project.removeFromPluginsPbxGroup(this.file); - test.done(); - } -} + const foundInGroup = findChildInGroup(project.pbxGroupByName('Plugins'), this.file.fileRef); + assert.ok(!foundInGroup); + }); -exports.addResourceFileToGroup = { - 'should add resource file (PNG) to the splash group' : function(test) { + it('should add a file to "Resources" group', () => { + project.addToResourcesPbxGroup(this.file); - var testKey = project.findPBXGroupKey({path:'splash'}); - var file = project.addResourceFile('DefaultTest-667h.png', {}, testKey); + const foundInGroup = findChildInGroup(project.pbxGroupByName('Resources'), this.file.fileRef); + assert.ok(foundInGroup); + }); - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(foundInGroup); + it('should remove a file from "Resources" group', () => { + project.addToResourcesPbxGroup(this.file); + project.removeFromResourcesPbxGroup(this.file); - test.done(); - } -} + const foundInGroup = findChildInGroup(project.pbxGroupByName('Resources'), this.file.fileRef); + assert.ok(!foundInGroup); + }); -exports.removeResourceFileFromGroup = { - 'should add resource file (PNG) then remove resource file from splash group' : function(test) { - var testKey = project.findPBXGroupKey({path:'splash'}); - var file = project.addResourceFile('DefaultTest-667h.png', {}, testKey); + it('should add a file to "Frameworks" group', () => { + project.addToFrameworksPbxGroup(this.file); - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(foundInGroup); + const foundInGroup = findChildInGroup(project.pbxGroupByName('Frameworks'), this.file.fileRef); + assert.ok(foundInGroup); + }); - project.removeResourceFile('DefaultTest-667h.png', {}, testKey); + it('should remove a file from "Frameworks" group', () => { + project.addToFrameworksPbxGroup(this.file); + project.removeFromFrameworksPbxGroup(this.file); - var foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey),file.fileRef ); - test.ok(!foundInGroup); + const foundInGroup = findChildInGroup(project.pbxGroupByName('Frameworks'), this.file.fileRef); + assert.ok(!foundInGroup); + }); - test.done(); - } -} + it('should add a file to "Products" group', () => { + project.addToProductsPbxGroup(this.file); -exports.retrieveBuildPropertyForBuild = { - 'should retrieve valid build property ':function(test) { - var releaseTargetedDeviceFamily = project.getBuildProperty('TARGETED_DEVICE_FAMILY', 'Release'); - var debugTargetedDeviceFamily = project.getBuildProperty('TARGETED_DEVICE_FAMILY', 'Debug'); - var nonExistingProperty = project.getBuildProperty('FOO', 'Debug'); - var nonExistingBuild = project.getBuildProperty('TARGETED_DEVICE_FAMILY', 'Foo'); + const foundInGroup = findChildInGroup(project.pbxGroupByName('Products'), this.file.fileRef); + assert.ok(foundInGroup); + }); - test.equal(releaseTargetedDeviceFamily, '"1,2"'); - test.equal(debugTargetedDeviceFamily,'"1"'); - test.equal(nonExistingProperty, undefined); - test.equal(nonExistingBuild, undefined); + it('should remove a file from "Products" group', () => { + project.addToProductsPbxGroup(this.file); + project.removeFromProductsPbxGroup(this.file); - test.done(); - } -} - -exports.retrieveBuildConfigByName = { - 'should retrieve valid build config':function(test) { - var releaseBuildConfig = project.getBuildConfigByName('Release'); - for (var property in releaseBuildConfig) { - var value = releaseBuildConfig[property]; - test.ok(value.name === 'Release'); - } + const foundInGroup = findChildInGroup(project.pbxGroupByName('Products'), this.file.fileRef); + assert.ok(!foundInGroup); + }); + }); - var debugBuildConfig = project.getBuildConfigByName('Debug'); - for (var property in debugBuildConfig) { - var value = debugBuildConfig[property]; - test.ok(value.name === 'Debug'); - } + describe('addSourceFileToGroup', () => { + it('should create group + add source file', () => { + const testKey = project.pbxCreateGroup('Test', 'Test'); + const file = project.addSourceFile('Notifications.m', {}, testKey); - var nonExistingBuildConfig = project.getBuildConfigByName('Foo'); - test.deepEqual(nonExistingBuildConfig, {}); + const foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(foundInGroup); - test.done(); - } -} - -/* This proves the issue in 0.6.7 -exports.validatePropReplaceException = { - 'should throw TypeError for updateBuildProperty VALID_ARCHS when none existed' : function(test) { - test.throws( - function() { - project.updateBuildProperty('VALID_ARCHS', '"armv7 armv7s'); - }, - TypeError, - "Object object has no method 'hasOwnProperty'" - ); - test.done(); - } -} -*/ + const foundInBuildFileSection = findByFileRef(project.pbxBuildFileSection(), file.fileRef); + assert.ok(foundInBuildFileSection); + + const foundInBuildPhase = findFileByUUID(project.pbxSourcesBuildPhaseObj(), file.uuid); + assert.ok(foundInBuildPhase); + }); + }); + + describe('removeSourceFileFromGroup', () => { + it('should create group + add source file then remove source file', () => { + const testKey = project.pbxCreateGroup('Test', 'Test'); + const file = project.addSourceFile('Notifications.m', {}, testKey); + + let foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(foundInGroup); + + let foundInBuildFileSection = findByFileRef(project.pbxBuildFileSection(), file.fileRef); + assert.ok(foundInBuildFileSection); + + let foundInBuildPhase = findFileByUUID(project.pbxSourcesBuildPhaseObj(), file.uuid); + assert.ok(foundInBuildPhase); + + project.removeSourceFile('Notifications.m', {}, testKey); + + foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(!foundInGroup); + + foundInBuildFileSection = findByFileRef(project.pbxBuildFileSection(), file.fileRef); + assert.ok(!foundInBuildFileSection); + + foundInBuildPhase = findFileByUUID(project.pbxSourcesBuildPhaseObj(), file.uuid); + assert.ok(!foundInBuildPhase); + }); + }); + + describe('addHeaderFileToGroup', () => { + it('should create group + add header file', () => { + const testKey = project.pbxCreateGroup('Test', 'Test'); + const file = project.addHeaderFile('Notifications.h', {}, testKey); + + const foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(foundInGroup); + }); + }); + + describe('removeHeaderFileFromGroup', () => { + it('should create group + add source file then remove header file', () => { + const testKey = project.pbxCreateGroup('Test', 'Test'); + const file = project.addHeaderFile('Notifications.h', {}, testKey); + + let foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(foundInGroup); + + project.removeHeaderFile('Notifications.h', {}, testKey); + + foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(!foundInGroup); + }); + }); + + describe('addResourceFileToGroup', () => { + it('should add resource file (PNG) to the splash group', () => { + const testKey = project.findPBXGroupKey({ path: 'splash' }); + const file = project.addResourceFile('DefaultTest-667h.png', {}, testKey); + + const foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(foundInGroup); + }); + }); + + describe('removeResourceFileFromGroup', () => { + it('should add resource file (PNG) then remove resource file from splash group', () => { + const testKey = project.findPBXGroupKey({ path: 'splash' }); + const file = project.addResourceFile('DefaultTest-667h.png', {}, testKey); + + let foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(foundInGroup); + + project.removeResourceFile('DefaultTest-667h.png', {}, testKey); + + foundInGroup = findChildInGroup(project.getPBXGroupByKey(testKey), file.fileRef); + assert.ok(!foundInGroup); + }); + }); + + describe('retrieveBuildPropertyForBuild', () => { + it('should retrieve valid build property ', () => { + const releaseTargetedDeviceFamily = project.getBuildProperty('TARGETED_DEVICE_FAMILY', 'Release'); + const debugTargetedDeviceFamily = project.getBuildProperty('TARGETED_DEVICE_FAMILY', 'Debug'); + const nonExistingProperty = project.getBuildProperty('FOO', 'Debug'); + const nonExistingBuild = project.getBuildProperty('TARGETED_DEVICE_FAMILY', 'Foo'); + + assert.equal(releaseTargetedDeviceFamily, '"1,2"'); + assert.equal(debugTargetedDeviceFamily, '"1"'); + assert.equal(nonExistingProperty, undefined); + assert.equal(nonExistingBuild, undefined); + }); + }); + + describe('retrieveBuildConfigByName', () => { + it('should retrieve valid build config', () => { + const releaseBuildConfig = project.getBuildConfigByName('Release'); + for (const property in releaseBuildConfig) { + const value = releaseBuildConfig[property]; + assert.ok(value.name === 'Release'); + } -exports.validatePropReplaceFix = { - 'should create build configuration for VALID_ARCHS when none existed' : function(test) { - project.updateBuildProperty('VALID_ARCHS', '"armv7 armv7s"', 'Debug'); - test.done(); - } -} + const debugBuildConfig = project.getBuildConfigByName('Debug'); + for (const property in debugBuildConfig) { + const value = debugBuildConfig[property]; + assert.ok(value.name === 'Debug'); + } -exports.validateHasFile = { - 'should return true for has file MainViewController.m': function(test) { - var result = project.hasFile('MainViewController.m'); - test.ok(result.path == "MainViewController.m"); - test.done(); + const nonExistingBuildConfig = project.getBuildConfigByName('Foo'); + assert.deepEqual(nonExistingBuildConfig, {}); + }); + }); + + /* This proves the issue in 0.6.7 + describe('validatePropReplaceException', () => { + it('should throw TypeError for updateBuildProperty VALID_ARCHS when none existed', () => { + assert.throws( + function() { + project.updateBuildProperty('VALID_ARCHS', '"armv7 armv7s'); + }, + TypeError, + "Object object has no method 'hasOwnProperty'" + ); + }); } -} - -exports.testWritingPBXProject = { - 'should successfully write to PBXProject TargetAttributes': function(test) { - var pbxProjectObj = project.getPBXObject('PBXProject'); - var pbxProject; - for (var property in pbxProjectObj) { - if (!/comment/.test(property)) { - pbxProject = pbxProjectObj[property]; + */ + + describe('validatePropReplaceFix', () => { + it('should create build configuration for VALID_ARCHS when none existed', () => { + project.updateBuildProperty('VALID_ARCHS', '"armv7 armv7s"', 'Debug'); + }); + }); + + describe('validateHasFile', () => { + it('should return true for has file MainViewController.m', () => { + const result = project.hasFile('MainViewController.m'); + assert.ok(result.path === 'MainViewController.m'); + }); + }); + + describe('testWritingPBXProject', () => { + it('should successfully write to PBXProject TargetAttributes', () => { + const pbxProjectObj = project.getPBXObject('PBXProject'); + let pbxProject; + for (const property in pbxProjectObj) { + if (!/comment/.test(property)) { + pbxProject = pbxProjectObj[property]; + } } - } - var target; - var projectTargets = pbxProject.targets; - for (var i = 0, j = pbxProject.targets.length; i < j; i++ ) { - target = pbxProject.targets[i].value; - } + let target; + for (let i = 0, j = pbxProject.targets.length; i < j; i++) { + target = pbxProject.targets[i].value; + } - pbxProject.attributes.TargetAttributes = {}; - pbxProject.attributes.TargetAttributes[target] = { - DevelopmentTeam: 'N6X4RJZZ5D', - SystemCapabilities: { - "com.apple.BackgroundModes": { - enabled : 0 + pbxProject.attributes.TargetAttributes = {}; + pbxProject.attributes.TargetAttributes[target] = { + DevelopmentTeam: 'N6X4RJZZ5D', + SystemCapabilities: { + 'com.apple.BackgroundModes': { + enabled: 0 + }, + 'com.apple.DataProtection': { + enabled: 0 + }, + 'com.apple.Keychain': { + enabled: 1 + } + } + }; + + project.writeSync(); + }); + + it('should add target attribute to PBXProject TargetAttributes', () => { + project.addTargetAttribute('ProvisioningStyle', 'Manual'); + const output = project.writeSync(); + assert.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g).length, 1); + }); + + it('should change target attribute at PBXProject TargetAttributes', () => { + project.addTargetAttribute('ProvisioningStyle', 'Manual'); + let output = project.writeSync(); + assert.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g).length, 1); + + project.addTargetAttribute('ProvisioningStyle', 'Automatic'); + output = project.writeSync(); + assert.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g), null); + assert.equal(output.match(/ProvisioningStyle\s*=\s*Automatic/g).length, 1); + }); + + it('should remove target attribute from PBXProject TargetAttributes', () => { + project.addTargetAttribute('ProvisioningStyle', 'Manual'); + let output = project.writeSync(); + assert.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g).length, 1); + + project.removeTargetAttribute('ProvisioningStyle'); + output = project.writeSync(); + assert.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g), null); + }); + + it('should not throw error when a non-restricted value is used for a target.uuid.', () => { + assert.doesNotThrow( + () => { + project.addTargetAttribute('ProvisioningStyle', 'Manual', { uuid: 'FooBar' }); }, - "com.apple.DataProtection" : { - enabled : 0 + /Error: "FooBar" is restricted and cannot be used as a uuid\./ + ); + }); + + it('should throw error when a restricted value was passed in for a target.uuid.', () => { + assert.throws( + () => { + project.addTargetAttribute('ProvisioningStyle', 'Manual', { uuid: 'prototype' }); }, - "com.apple.Keychain" : { - enabled: 1 - } - } - }; - - var output = project.writeSync(); - - test.done(); - }, - 'should add target attribute to PBXProject TargetAttributes': function(test) { - project.addTargetAttribute('ProvisioningStyle', 'Manual'); - var output = project.writeSync(); - test.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g).length, 1); - - test.done(); - }, - 'should change target attribute at PBXProject TargetAttributes': function(test) { - project.addTargetAttribute('ProvisioningStyle', 'Manual'); - var output = project.writeSync(); - test.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g).length, 1); - - project.addTargetAttribute('ProvisioningStyle', 'Automatic'); - output = project.writeSync(); - test.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g), null); - test.equal(output.match(/ProvisioningStyle\s*=\s*Automatic/g).length, 1); - - test.done(); - }, - 'should remove target attribute from PBXProject TargetAttributes': function(test) { - project.addTargetAttribute('ProvisioningStyle', 'Manual'); - var output = project.writeSync(); - test.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g).length, 1); - - project.removeTargetAttribute('ProvisioningStyle'); - output = project.writeSync(); - test.equal(output.match(/ProvisioningStyle\s*=\s*Manual/g), null); - - test.done(); - } -} + /Error: "prototype" is restricted and cannot be used as a uuid\./ + ); + }); + }); +}); diff --git a/test/knownRegions.js b/test/knownRegions.js index 08ce4542..f005c7a8 100644 --- a/test/knownRegions.js +++ b/test/knownRegions.js @@ -1,93 +1,91 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - project = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const project = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - project.hash = cleanHash(); - callback(); -} +describe('knownRegions', () => { + beforeEach(() => { + project.hash = cleanHash(); + }); -exports.addKnownRegion = { - 'should add new region to existing knownRegions': function (test) { - var knownRegions = project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions']; - test.equal(knownRegions.indexOf('Spanish'), -1); - - project.addKnownRegion('Spanish') - knownRegions = project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions']; - test.notEqual(knownRegions.indexOf('Spanish'), -1); - test.done(); - }, - - 'should not add region if it already exists in knownRegions': function (test) { - var numberOfRegions = project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions'].length; - - project.addKnownRegion('German'); - var newNumberOfRegions = project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions'].length; - test.equal(numberOfRegions, newNumberOfRegions); - test.done(); - }, - - 'should create knownRegions array if it does not exist': function (test) { - delete project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions']; - test.ok(!project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions']); - - project.addKnownRegion('German') - test.ok(project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions']); - test.done(); - }, -} + describe('addKnownRegion', () => { + it('should add new region to existing knownRegions', () => { + let knownRegions = project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions; + assert.equal(knownRegions.indexOf('Spanish'), -1); -exports.removeKnownRegion = { - 'should remove named region from knownRegions': function (test) { - var knownRegions = project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions']; - test.notEqual(knownRegions.indexOf('German'), -1); - - project.removeKnownRegion('German'); - knownRegions = project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions']; - test.equal(knownRegions.indexOf('German'), -1); - test.done(); - }, - - 'should do nothing if named region does not exist in knownRegions': function (test) { - var numberOfRegions = project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions'].length; - - project.removeKnownRegion('Korean'); - var newNumberOfRegions = project.pbxProjectSection()[project.getFirstProject()['uuid']]['knownRegions'].length; - test.equal(numberOfRegions, newNumberOfRegions); - test.done(); - }, -} + project.addKnownRegion('Spanish'); + knownRegions = project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions; + assert.notEqual(knownRegions.indexOf('Spanish'), -1); + }); -exports.hasKnownRegion = { - 'should return true if named region exists in knownRegions': function (test) { - test.ok(project.hasKnownRegion('German')); - test.done(); - }, + it('should not add region if it already exists in knownRegions', () => { + const numberOfRegions = project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions.length; - 'should return false if named region does not exist in knownRegions': function (test) { - test.ok(!project.hasKnownRegion('Ducth')); - test.done(); - }, -} + project.addKnownRegion('German'); + const newNumberOfRegions = project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions.length; + assert.equal(numberOfRegions, newNumberOfRegions); + }); + + it('should create knownRegions array if it does not exist', () => { + delete project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions; + assert.ok(!project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions); + + project.addKnownRegion('German'); + assert.ok(project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions); + }); + }); + + describe('removeKnownRegion', () => { + it('should remove named region from knownRegions', () => { + let knownRegions = project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions; + assert.notEqual(knownRegions.indexOf('German'), -1); + + project.removeKnownRegion('German'); + knownRegions = project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions; + assert.equal(knownRegions.indexOf('German'), -1); + }); + + it('should do nothing if named region does not exist in knownRegions', () => { + const numberOfRegions = project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions.length; + + project.removeKnownRegion('Korean'); + const newNumberOfRegions = project.pbxProjectSection()[project.getFirstProject().uuid].knownRegions.length; + assert.equal(numberOfRegions, newNumberOfRegions); + }); + }); + + describe('hasKnownRegion', () => { + it('should return true if named region exists in knownRegions', () => { + assert.ok(project.hasKnownRegion('German')); + }); + + it('should return false if named region does not exist in knownRegions', () => { + assert.ok(!project.hasKnownRegion('Ducth')); + }); + }); +}); diff --git a/test/multipleTargets.js b/test/multipleTargets.js index dbb945f7..34fcdaf8 100644 --- a/test/multipleTargets.js +++ b/test/multipleTargets.js @@ -1,170 +1,152 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/multiple-targets') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/multiple-targets'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.addFilesToTarget = { - 'should add the file to a proper target': function (test) { - - var target = "1D6058900D05DD3D006BFB54"; - var filename = "file.m"; - - var opt = { target : target }; - var newFile = proj.addSourceFile(filename,opt); +describe('addFilesToTarget', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); - test.equal(newFile.constructor, pbxFile); + it('should add the file to a proper target', () => { + const target = '1D6058900D05DD3D006BFB54'; + const filename = 'file.m'; - var sources = proj.pbxSourcesBuildPhaseObj(target); - test.equal(sources.files[5].comment, filename+" in Sources"); + const opt = { target }; + const newFile = proj.addSourceFile(filename, opt); - test.done(); - }, - 'should remove the file from the proper target': function (test) { + assert.equal(newFile.constructor, PBXFile); - var target = "1D6058900D05DD3D006BFB54"; - var filename = "file.m"; + const sources = proj.pbxSourcesBuildPhaseObj(target); + assert.equal(sources.files[5].comment, filename + ' in Sources'); + }); - var opt = { target : target }; - var newFile = proj.addSourceFile(filename,opt); + it('should remove the file from the proper target', () => { + const target = '1D6058900D05DD3D006BFB54'; + const filename = 'file.m'; - test.equal(newFile.constructor, pbxFile); + const opt = { target }; + const newFile = proj.addSourceFile(filename, opt); - var sources = proj.pbxSourcesBuildPhaseObj(target); - test.equal(sources.files[5].comment, filename+" in Sources"); - var l = sources.files.length; + assert.equal(newFile.constructor, PBXFile); - proj.removeSourceFile(filename,opt); - var sources = proj.pbxSourcesBuildPhaseObj(target); - test.equal(sources.files.length,l-1); + let sources = proj.pbxSourcesBuildPhaseObj(target); + assert.equal(sources.files[5].comment, filename + ' in Sources'); + const l = sources.files.length; - test.done(); - }, - 'should fail when specifying an invalid target': function (test) { + proj.removeSourceFile(filename, opt); + sources = proj.pbxSourcesBuildPhaseObj(target); + assert.equal(sources.files.length, l - 1); + }); - var target = "XXXXX"; - var filename = "file.m"; + it('should fail when specifying an invalid target', () => { + const target = 'XXXXX'; + const filename = 'file.m'; - var opt = { target : target }; - test.throws(function(){ - proj.addSourceFile(filename,opt); + const opt = { target }; + assert.throws(function () { + proj.addSourceFile(filename, opt); }); + }); + it('should add the library to a proper target', () => { + const target = '1D6058900D05DD3D006BFB54'; + const filename = 'library.lib'; + const opt = { target }; + const newFile = proj.addStaticLibrary(filename, opt); - test.done(); - }, - 'should add the library to a proper target': function (test) { - - var target = "1D6058900D05DD3D006BFB54"; - var filename = "library.lib"; - - var opt = { target : target }; - var newFile = proj.addStaticLibrary(filename,opt); - - test.equal(newFile.constructor, pbxFile); - - var libraries = proj.pbxFrameworksBuildPhaseObj(target); - test.equal(libraries.files[4].comment, filename+" in Resources"); + assert.equal(newFile.constructor, PBXFile); - test.done(); - }, - 'should remove the library to a proper target': function (test) { + const libraries = proj.pbxFrameworksBuildPhaseObj(target); + assert.equal(libraries.files[4].comment, filename + ' in Resources'); + }); - var target = "1D6058900D05DD3D006BFB54"; - var filename = "library.lib"; + it('should remove the library to a proper target', () => { + const target = '1D6058900D05DD3D006BFB54'; + const filename = 'library.lib'; - var opt = { target : target }; - var newFile = proj.addStaticLibrary(filename,opt); + const opt = { target }; + const newFile = proj.addStaticLibrary(filename, opt); - test.equal(newFile.constructor, pbxFile); + assert.equal(newFile.constructor, PBXFile); - var libraries = proj.pbxFrameworksBuildPhaseObj(target); - test.equal(libraries.files[4].comment, filename+" in Resources"); - var l = libraries.files.length; + let libraries = proj.pbxFrameworksBuildPhaseObj(target); + assert.equal(libraries.files[4].comment, filename + ' in Resources'); + const l = libraries.files.length; - proj.removeFramework(filename,opt); - var libraries = proj.pbxFrameworksBuildPhaseObj(target); - test.equal(libraries.files.length,l-1); + proj.removeFramework(filename, opt); + libraries = proj.pbxFrameworksBuildPhaseObj(target); + assert.equal(libraries.files.length, l - 1); + }); - test.done(); + it('should add the framework to a proper target', () => { + const target = '1D6058900D05DD3D006BFB54'; + const filename = 'delta.framework'; - }, - 'should add the framework to a proper target': function (test) { + const opt = { target }; + const newFile = proj.addFramework(filename, opt); - var target = "1D6058900D05DD3D006BFB54"; - var filename = "delta.framework"; + assert.equal(newFile.constructor, PBXFile); - var opt = { target : target }; - var newFile = proj.addFramework(filename,opt); + const frameworks = proj.pbxFrameworksBuildPhaseObj(target); + assert.equal(frameworks.files[4].comment, filename + ' in Frameworks'); + }); - test.equal(newFile.constructor, pbxFile); + it('should add a ressource fileto a proper target', () => { + const target = '1D6058900D05DD3D006BFB54'; + const filename = 'delta.png'; - var frameworks = proj.pbxFrameworksBuildPhaseObj(target); - test.equal(frameworks.files[4].comment, filename+" in Frameworks"); + const opt = { target }; + const newFile = proj.addResourceFile(filename, opt); - test.done(); - }, - 'should add a ressource fileto a proper target': function (test) { + assert.equal(newFile.constructor, PBXFile); - var target = "1D6058900D05DD3D006BFB54"; - var filename = "delta.png"; + const resources = proj.pbxResourcesBuildPhaseObj(target); + assert.equal(resources.files[26].comment, filename + ' in Resources'); + }); + it('should remove a ressource file from a proper target', () => { + const target = '1D6058900D05DD3D006BFB54'; + const filename = 'delta.png'; - var opt = { target : target }; - var newFile = proj.addResourceFile(filename,opt); + const opt = { target }; + const newFile = proj.addResourceFile(filename, opt); - test.equal(newFile.constructor, pbxFile); + assert.equal(newFile.constructor, PBXFile); - var resources = proj.pbxResourcesBuildPhaseObj(target); - test.equal(resources.files[26].comment, filename+" in Resources"); + let resources = proj.pbxResourcesBuildPhaseObj(target); + assert.equal(resources.files[26].comment, filename + ' in Resources'); - test.done(); - }, - 'should remove a ressource file from a proper target': function (test) { - - var target = "1D6058900D05DD3D006BFB54"; - var filename = "delta.png"; - - var opt = { target : target }; - var newFile = proj.addResourceFile(filename,opt); - - test.equal(newFile.constructor, pbxFile); - - var resources = proj.pbxResourcesBuildPhaseObj(target); - test.equal(resources.files[26].comment, filename+" in Resources"); - - var l = resources.files.length; - - proj.removeResourceFile(filename,opt); - var resources = proj.pbxResourcesBuildPhaseObj(target); - test.equal(resources.files.length,l-1); - - test.done(); - }, -} + const l = resources.files.length; + proj.removeResourceFile(filename, opt); + resources = proj.pbxResourcesBuildPhaseObj(target); + assert.equal(resources.files.length, l - 1); + }); +}); diff --git a/test/parser/build-config.js b/test/parser/build-config.js index 465c352e..078ec2cd 100644 --- a/test/parser/build-config.js +++ b/test/parser/build-config.js @@ -1,47 +1,50 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/build-config.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - util = require('util'), - project = rawProj.project; - -exports['should parse the build config section'] = function (test) { - // if it gets this far it's worked - test.done(); -} - -exports['should read a decimal value correctly'] = function (test) { - var xcbConfig = project.objects['XCBuildConfiguration'], - debugSettings = xcbConfig['1D6058950D05DD3E006BFB54'].buildSettings; - - test.strictEqual(debugSettings['IPHONEOS_DEPLOYMENT_TARGET'], '3.0'); - test.done(); -} - -exports['should read an escaped value correctly'] = function (test) { - var xcbConfig = project.objects['XCBuildConfiguration'], - debugSettings = xcbConfig['C01FCF4F08A954540054247B'].buildSettings, - expt = '"\\"$(PHONEGAPLIB)/Classes/JSON\\" \\"$(PHONEGAPLIB)/Classes\\""'; - - test.strictEqual(debugSettings['USER_HEADER_SEARCH_PATHS'], expt); - test.done(); -} +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); +const assert = require('node:assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/build-config.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/build-config', () => { + it('should parse the build config section', () => { + // if it gets this far it's worked + }); + + it('should read a decimal value correctly', () => { + const xcbConfig = project.objects.XCBuildConfiguration; + const debugSettings = xcbConfig['1D6058950D05DD3E006BFB54'].buildSettings; + + assert.strictEqual(debugSettings.IPHONEOS_DEPLOYMENT_TARGET, '3.0'); + }); + + it('should read an escaped value correctly', () => { + const xcbConfig = project.objects.XCBuildConfiguration; + const debugSettings = xcbConfig.C01FCF4F08A954540054247B.buildSettings; + const expt = '"\\"$(PHONEGAPLIB)/Classes/JSON\\" \\"$(PHONEGAPLIB)/Classes\\""'; + + assert.strictEqual(debugSettings.USER_HEADER_SEARCH_PATHS, expt); + }); +}); diff --git a/test/parser/comments.js b/test/parser/comments.js index 7be4c38c..22c8ffd9 100644 --- a/test/parser/comments.js +++ b/test/parser/comments.js @@ -1,29 +1,34 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/comments.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar); + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/comments.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); // Cordova 1.8 has the Apache headers as comments in the pbxproj file // I DON'T KNOW WHY -exports['should ignore comments outside the main object'] = function (test) { - parser.parse(pbx); - test.done(); -} +describe('parser/comments', () => { + it('should ignore comments outside the main object', () => { + parser.parse(pbx); + }); +}); diff --git a/test/parser/dotsInNames.js b/test/parser/dotsInNames.js index 4121bba7..ede77ef6 100644 --- a/test/parser/dotsInNames.js +++ b/test/parser/dotsInNames.js @@ -1,32 +1,38 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/dots-in-names.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; + http://www.apache.org/licenses/LICENSE-2.0 -exports['should parse com.apple.BackgroundModes'] = function (test) { - var targets = project.attributes.TargetAttributes['1D6058900D05DD3D006BFB54'], - backgroundModes = targets.SystemCapabilities['com.apple.BackgroundModes']; + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ - test.deepEqual(backgroundModes, {enabled: 1}); - test.done() -} +const { describe, it } = require('node:test'); +const assert = require('node:assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/dots-in-names.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/dotsInNames', () => { + it('should parse com.apple.BackgroundModes', () => { + const targets = project.attributes.TargetAttributes['1D6058900D05DD3D006BFB54']; + const backgroundModes = targets.SystemCapabilities['com.apple.BackgroundModes']; + + assert.deepEqual(backgroundModes, { enabled: 1 }); + }); +}); diff --git a/test/parser/file-references.js b/test/parser/file-references.js index 42753785..a83884ea 100644 --- a/test/parser/file-references.js +++ b/test/parser/file-references.js @@ -1,29 +1,35 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/file-references.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; + http://www.apache.org/licenses/LICENSE-2.0 -exports['should have a PBXFileReference section'] = function (test) { - test.ok(project.objects['PBXFileReference']); - test.done(); -} + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); +const assert = require('assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/file-references.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/file-references', () => { + it('should have a PBXFileReference section', () => { + assert.ok(project.objects.PBXFileReference); + }); +}); diff --git a/test/parser/hash.js b/test/parser/hash.js index 6ec8106c..31a57bb2 100644 --- a/test/parser/hash.js +++ b/test/parser/hash.js @@ -1,52 +1,54 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/hash.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; - -exports['should have the top-line comment in place'] = function (test) { - test.equals(rawProj.headComment, '!$*UTF8*$!'); - test.done() -} - -exports['should parse a numeric attribute'] = function (test) { - test.strictEqual(project.archiveVersion, 1); - test.strictEqual(project.objectVersion, 45); - test.done() -} - -exports['should parse an empty object'] = function (test) { - var empty = project.classes; - test.equal(Object.keys(empty).length, 0); - test.done() -} - -exports['should split out properties and comments'] = function (test) { - test.equal(project.rootObject, '29B97313FDCFA39411CA2CEA'); - test.equal(project['rootObject_comment'], 'Project object'); - test.done(); -} - -exports['should parse non-commented hash things'] = function (test) { - test.equal(project.nonObject, '29B97313FDCFA39411CA2CEF'); - test.done(); -} +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); +const assert = require('assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/hash.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/hash', () => { + it('should have the top-line comment in place', () => { + assert.strictEqual(rawProj.headComment, '!$*UTF8*$!'); + }); + + it('should parse a numeric attribute', () => { + assert.strictEqual(project.archiveVersion, 1); + assert.strictEqual(project.objectVersion, 45); + }); + + it('should parse an empty object', () => { + const empty = project.classes; + assert.strictEqual(Object.keys(empty).length, 0); + }); + + it('should split out properties and comments', () => { + assert.strictEqual(project.rootObject, '29B97313FDCFA39411CA2CEA'); + assert.strictEqual(project.rootObject_comment, 'Project object'); + }); + + it('should parse non-commented hash things', () => { + assert.strictEqual(project.nonObject, '29B97313FDCFA39411CA2CEF'); + }); +}); diff --git a/test/parser/header-search.js b/test/parser/header-search.js index 226c301a..6776e17c 100644 --- a/test/parser/header-search.js +++ b/test/parser/header-search.js @@ -1,33 +1,39 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/header-search.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; + http://www.apache.org/licenses/LICENSE-2.0 -exports['should read a decimal value correctly'] = function (test) { - var debug = project.objects['XCBuildConfiguration']['C01FCF4F08A954540054247B'], - hsPaths = debug.buildSettings['HEADER_SEARCH_PATHS'], - expected = '"\\"$(TARGET_BUILD_DIR)/usr/local/lib/include\\""'; + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ - test.equal(hsPaths[0], expected); - test.done(); -} +const { describe, it } = require('node:test'); +const assert = require('assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/header-search.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/header-search', () => { + it('should read a decimal value correctly', () => { + const debug = project.objects.XCBuildConfiguration.C01FCF4F08A954540054247B; + const hsPaths = debug.buildSettings.HEADER_SEARCH_PATHS; + const expected = '"\\"$(TARGET_BUILD_DIR)/usr/local/lib/include\\""'; + + assert.strictEqual(hsPaths[0], expected); + }); +}); diff --git a/test/parser/projects/comments.pbxproj b/test/parser/projects/comments.pbxproj index 977bb5e5..4c71aab8 100644 --- a/test/parser/projects/comments.pbxproj +++ b/test/parser/projects/comments.pbxproj @@ -1,23 +1,21 @@ // !$*UTF8*$! /* -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. */ { archiveVersion = 1; diff --git a/test/parser/projects/multitarget.pbxproj b/test/parser/projects/multitarget.pbxproj new file mode 100644 index 00000000..cca1b038 --- /dev/null +++ b/test/parser/projects/multitarget.pbxproj @@ -0,0 +1,729 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 944D366F243CEEF7003126AD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944D366E243CEEF7003126AD /* AppDelegate.swift */; }; + 944D3671243CEEF7003126AD /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944D3670243CEEF7003126AD /* SceneDelegate.swift */; }; + 944D3673243CEEF7003126AD /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944D3672243CEEF7003126AD /* ContentView.swift */; }; + 944D3675243CEEFA003126AD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 944D3674243CEEFA003126AD /* Assets.xcassets */; }; + 944D3678243CEEFA003126AD /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 944D3677243CEEFA003126AD /* Preview Assets.xcassets */; }; + 944D367B243CEEFA003126AD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 944D3679243CEEFA003126AD /* LaunchScreen.storyboard */; }; + 944D3686243CEEFB003126AD /* MultiTargetTestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944D3685243CEEFB003126AD /* MultiTargetTestTests.swift */; }; + 944D3691243CEEFB003126AD /* MultiTargetTestUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944D3690243CEEFB003126AD /* MultiTargetTestUITests.swift */; }; + 944D36A5243CEF1C003126AD /* CallDirectoryHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 944D36A4243CEF1C003126AD /* CallDirectoryHandler.swift */; }; + 944D36A9243CEF1C003126AD /* CalldirectoryTarget.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 944D36A2243CEF1C003126AD /* CalldirectoryTarget.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 944D3682243CEEFB003126AD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 944D3663243CEEF7003126AD /* Project object */; + proxyType = 1; + remoteGlobalIDString = 944D366A243CEEF7003126AD; + remoteInfo = MultiTargetTest; + }; + 944D368D243CEEFB003126AD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 944D3663243CEEF7003126AD /* Project object */; + proxyType = 1; + remoteGlobalIDString = 944D366A243CEEF7003126AD; + remoteInfo = MultiTargetTest; + }; + 944D36A7243CEF1C003126AD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 944D3663243CEEF7003126AD /* Project object */; + proxyType = 1; + remoteGlobalIDString = 944D36A1243CEF1C003126AD; + remoteInfo = CalldirectoryTarget; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 944D36AD243CEF1C003126AD /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 944D36A9243CEF1C003126AD /* CalldirectoryTarget.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 944D366B243CEEF7003126AD /* MultiTargetTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MultiTargetTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 944D366E243CEEF7003126AD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 944D3670243CEEF7003126AD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 944D3672243CEEF7003126AD /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 944D3674243CEEFA003126AD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 944D3677243CEEFA003126AD /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 944D367A243CEEFA003126AD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 944D367C243CEEFA003126AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 944D3681243CEEFB003126AD /* MultiTargetTestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MultiTargetTestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 944D3685243CEEFB003126AD /* MultiTargetTestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiTargetTestTests.swift; sourceTree = ""; }; + 944D3687243CEEFB003126AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 944D368C243CEEFB003126AD /* MultiTargetTestUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MultiTargetTestUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 944D3690243CEEFB003126AD /* MultiTargetTestUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiTargetTestUITests.swift; sourceTree = ""; }; + 944D3692243CEEFB003126AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 944D36A2243CEF1C003126AD /* CalldirectoryTarget.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = CalldirectoryTarget.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 944D36A4243CEF1C003126AD /* CallDirectoryHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallDirectoryHandler.swift; sourceTree = ""; }; + 944D36A6243CEF1C003126AD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 944D3668243CEEF7003126AD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D367E243CEEFB003126AD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D3689243CEEFB003126AD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D369F243CEF1C003126AD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 944D3662243CEEF7003126AD = { + isa = PBXGroup; + children = ( + 944D366D243CEEF7003126AD /* MultiTargetTest */, + 944D3684243CEEFB003126AD /* MultiTargetTestTests */, + 944D368F243CEEFB003126AD /* MultiTargetTestUITests */, + 944D36A3243CEF1C003126AD /* CalldirectoryTarget */, + 944D366C243CEEF7003126AD /* Products */, + ); + sourceTree = ""; + }; + 944D366C243CEEF7003126AD /* Products */ = { + isa = PBXGroup; + children = ( + 944D366B243CEEF7003126AD /* MultiTargetTest.app */, + 944D3681243CEEFB003126AD /* MultiTargetTestTests.xctest */, + 944D368C243CEEFB003126AD /* MultiTargetTestUITests.xctest */, + 944D36A2243CEF1C003126AD /* CalldirectoryTarget.appex */, + ); + name = Products; + sourceTree = ""; + }; + 944D366D243CEEF7003126AD /* MultiTargetTest */ = { + isa = PBXGroup; + children = ( + 944D366E243CEEF7003126AD /* AppDelegate.swift */, + 944D3670243CEEF7003126AD /* SceneDelegate.swift */, + 944D3672243CEEF7003126AD /* ContentView.swift */, + 944D3674243CEEFA003126AD /* Assets.xcassets */, + 944D3679243CEEFA003126AD /* LaunchScreen.storyboard */, + 944D367C243CEEFA003126AD /* Info.plist */, + 944D3676243CEEFA003126AD /* Preview Content */, + ); + path = MultiTargetTest; + sourceTree = ""; + }; + 944D3676243CEEFA003126AD /* Preview Content */ = { + isa = PBXGroup; + children = ( + 944D3677243CEEFA003126AD /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 944D3684243CEEFB003126AD /* MultiTargetTestTests */ = { + isa = PBXGroup; + children = ( + 944D3685243CEEFB003126AD /* MultiTargetTestTests.swift */, + 944D3687243CEEFB003126AD /* Info.plist */, + ); + path = MultiTargetTestTests; + sourceTree = ""; + }; + 944D368F243CEEFB003126AD /* MultiTargetTestUITests */ = { + isa = PBXGroup; + children = ( + 944D3690243CEEFB003126AD /* MultiTargetTestUITests.swift */, + 944D3692243CEEFB003126AD /* Info.plist */, + ); + path = MultiTargetTestUITests; + sourceTree = ""; + }; + 944D36A3243CEF1C003126AD /* CalldirectoryTarget */ = { + isa = PBXGroup; + children = ( + 944D36A4243CEF1C003126AD /* CallDirectoryHandler.swift */, + 944D36A6243CEF1C003126AD /* Info.plist */, + ); + path = CalldirectoryTarget; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 944D366A243CEEF7003126AD /* MultiTargetTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 944D3695243CEEFB003126AD /* Build configuration list for PBXNativeTarget "MultiTargetTest" */; + buildPhases = ( + 944D3667243CEEF7003126AD /* Sources */, + 944D3668243CEEF7003126AD /* Frameworks */, + 944D3669243CEEF7003126AD /* Resources */, + 944D36AD243CEF1C003126AD /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + 944D36A8243CEF1C003126AD /* PBXTargetDependency */, + ); + name = MultiTargetTest; + productName = MultiTargetTest; + productReference = 944D366B243CEEF7003126AD /* MultiTargetTest.app */; + productType = "com.apple.product-type.application"; + }; + 944D3680243CEEFB003126AD /* MultiTargetTestTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 944D3698243CEEFB003126AD /* Build configuration list for PBXNativeTarget "MultiTargetTestTests" */; + buildPhases = ( + 944D367D243CEEFB003126AD /* Sources */, + 944D367E243CEEFB003126AD /* Frameworks */, + 944D367F243CEEFB003126AD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 944D3683243CEEFB003126AD /* PBXTargetDependency */, + ); + name = MultiTargetTestTests; + productName = MultiTargetTestTests; + productReference = 944D3681243CEEFB003126AD /* MultiTargetTestTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 944D368B243CEEFB003126AD /* MultiTargetTestUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 944D369B243CEEFB003126AD /* Build configuration list for PBXNativeTarget "MultiTargetTestUITests" */; + buildPhases = ( + 944D3688243CEEFB003126AD /* Sources */, + 944D3689243CEEFB003126AD /* Frameworks */, + 944D368A243CEEFB003126AD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 944D368E243CEEFB003126AD /* PBXTargetDependency */, + ); + name = MultiTargetTestUITests; + productName = MultiTargetTestUITests; + productReference = 944D368C243CEEFB003126AD /* MultiTargetTestUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; + 944D36A1243CEF1C003126AD /* CalldirectoryTarget */ = { + isa = PBXNativeTarget; + buildConfigurationList = 944D36AA243CEF1C003126AD /* Build configuration list for PBXNativeTarget "CalldirectoryTarget" */; + buildPhases = ( + 944D369E243CEF1C003126AD /* Sources */, + 944D369F243CEF1C003126AD /* Frameworks */, + 944D36A0243CEF1C003126AD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CalldirectoryTarget; + productName = CalldirectoryTarget; + productReference = 944D36A2243CEF1C003126AD /* CalldirectoryTarget.appex */; + productType = "com.apple.product-type.app-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 944D3663243CEEF7003126AD /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1140; + LastUpgradeCheck = 1140; + ORGANIZATIONNAME = "The Apache Software Foundation"; + TargetAttributes = { + 944D366A243CEEF7003126AD = { + CreatedOnToolsVersion = 11.4; + }; + 944D3680243CEEFB003126AD = { + CreatedOnToolsVersion = 11.4; + TestTargetID = 944D366A243CEEF7003126AD; + }; + 944D368B243CEEFB003126AD = { + CreatedOnToolsVersion = 11.4; + TestTargetID = 944D366A243CEEF7003126AD; + }; + 944D36A1243CEF1C003126AD = { + CreatedOnToolsVersion = 11.4; + }; + }; + }; + buildConfigurationList = 944D3666243CEEF7003126AD /* Build configuration list for PBXProject "MultiTargetTest" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 944D3662243CEEF7003126AD; + productRefGroup = 944D366C243CEEF7003126AD /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 944D366A243CEEF7003126AD /* MultiTargetTest */, + 944D3680243CEEFB003126AD /* MultiTargetTestTests */, + 944D368B243CEEFB003126AD /* MultiTargetTestUITests */, + 944D36A1243CEF1C003126AD /* CalldirectoryTarget */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 944D3669243CEEF7003126AD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 944D367B243CEEFA003126AD /* LaunchScreen.storyboard in Resources */, + 944D3678243CEEFA003126AD /* Preview Assets.xcassets in Resources */, + 944D3675243CEEFA003126AD /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D367F243CEEFB003126AD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D368A243CEEFB003126AD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D36A0243CEF1C003126AD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 944D3667243CEEF7003126AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 944D366F243CEEF7003126AD /* AppDelegate.swift in Sources */, + 944D3671243CEEF7003126AD /* SceneDelegate.swift in Sources */, + 944D3673243CEEF7003126AD /* ContentView.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D367D243CEEFB003126AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 944D3686243CEEFB003126AD /* MultiTargetTestTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D3688243CEEFB003126AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 944D3691243CEEFB003126AD /* MultiTargetTestUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 944D369E243CEF1C003126AD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 944D36A5243CEF1C003126AD /* CallDirectoryHandler.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 944D3683243CEEFB003126AD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 944D366A243CEEF7003126AD /* MultiTargetTest */; + targetProxy = 944D3682243CEEFB003126AD /* PBXContainerItemProxy */; + }; + 944D368E243CEEFB003126AD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 944D366A243CEEF7003126AD /* MultiTargetTest */; + targetProxy = 944D368D243CEEFB003126AD /* PBXContainerItemProxy */; + }; + 944D36A8243CEF1C003126AD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 944D36A1243CEF1C003126AD /* CalldirectoryTarget */; + targetProxy = 944D36A7243CEF1C003126AD /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 944D3679243CEEFA003126AD /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 944D367A243CEEFA003126AD /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 944D3693243CEEFB003126AD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 944D3694243CEEFB003126AD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 944D3696243CEEFB003126AD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"MultiTargetTest/Preview Content\""; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = MultiTargetTest/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.test.MultiTargetTest; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 944D3697243CEEFB003126AD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"MultiTargetTest/Preview Content\""; + ENABLE_PREVIEWS = YES; + INFOPLIST_FILE = MultiTargetTest/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.test.MultiTargetTest; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 944D3699243CEEFB003126AD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = MultiTargetTestTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.test.MultiTargetTestTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MultiTargetTest.app/MultiTargetTest"; + }; + name = Debug; + }; + 944D369A243CEEFB003126AD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = MultiTargetTestTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.test.MultiTargetTestTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MultiTargetTest.app/MultiTargetTest"; + }; + name = Release; + }; + 944D369C243CEEFB003126AD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = MultiTargetTestUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.test.MultiTargetTestUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = MultiTargetTest; + }; + name = Debug; + }; + 944D369D243CEEFB003126AD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = MultiTargetTestUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.test.MultiTargetTestUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = MultiTargetTest; + }; + name = Release; + }; + 944D36AB243CEF1C003126AD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = CalldirectoryTarget/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.test.MultiTargetTest.CalldirectoryTarget; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 944D36AC243CEF1C003126AD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = CalldirectoryTarget/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.apache.cordova.test.MultiTargetTest.CalldirectoryTarget; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 944D3666243CEEF7003126AD /* Build configuration list for PBXProject "MultiTargetTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 944D3693243CEEFB003126AD /* Debug */, + 944D3694243CEEFB003126AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 944D3695243CEEFB003126AD /* Build configuration list for PBXNativeTarget "MultiTargetTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 944D3696243CEEFB003126AD /* Debug */, + 944D3697243CEEFB003126AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 944D3698243CEEFB003126AD /* Build configuration list for PBXNativeTarget "MultiTargetTestTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 944D3699243CEEFB003126AD /* Debug */, + 944D369A243CEEFB003126AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 944D369B243CEEFB003126AD /* Build configuration list for PBXNativeTarget "MultiTargetTestUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 944D369C243CEEFB003126AD /* Debug */, + 944D369D243CEEFB003126AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 944D36AA243CEF1C003126AD /* Build configuration list for PBXNativeTarget "CalldirectoryTarget" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 944D36AB243CEF1C003126AD /* Debug */, + 944D36AC243CEF1C003126AD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 944D3663243CEEF7003126AD /* Project object */; +} diff --git a/test/parser/section-entries.js b/test/parser/section-entries.js index 56d578c0..1d1afd34 100644 --- a/test/parser/section-entries.js +++ b/test/parser/section-entries.js @@ -1,42 +1,46 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/section-entries.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; + http://www.apache.org/licenses/LICENSE-2.0 -exports['should have a PBXVariantGroup section'] = function (test) { - test.ok(project.objects['PBXVariantGroup']); - test.done(); -} + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ -exports['should have two children for PBXVariantGroup'] = function (test) { - test.ok(project.objects['PBXVariantGroup']['1F766FDF13BBADB100FB74C0']); - test.ok(project.objects['PBXVariantGroup']['1F766FDC13BBADB100FB74C0']); - test.done(); -} +const { describe, it } = require('node:test'); +const assert = require('assert'); -exports['should store quote-surround values correctly'] = function (test) { - var localizable = project.objects['PBXVariantGroup']['1F766FDF13BBADB100FB74C0']; +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/section-entries.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; - test.equal(localizable.sourceTree, '""'); - test.done(); -} +describe('parser/section-entries', () => { + it('should have a PBXVariantGroup section', () => { + assert.ok(project.objects.PBXVariantGroup); + }); + + it('should have two children for PBXVariantGroup', () => { + const variantGroup = project.objects.PBXVariantGroup; + assert.ok(variantGroup['1F766FDF13BBADB100FB74C0']); + assert.ok(variantGroup['1F766FDC13BBADB100FB74C0']); + }); + + it('should store quote-surround values correctly', () => { + const localizable = project.objects.PBXVariantGroup['1F766FDF13BBADB100FB74C0']; + assert.strictEqual(localizable.sourceTree, '""'); + }); +}); diff --git a/test/parser/section-split.js b/test/parser/section-split.js index cd17247d..84d7d220 100644 --- a/test/parser/section-split.js +++ b/test/parser/section-split.js @@ -1,52 +1,53 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/section-split.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; - -exports['should have a PBXTargetDependency section'] = function (test) { - test.ok(project.objects['PBXTargetDependency']); - test.done(); -} - -exports['should have the right child of PBXTargetDependency section'] = function (test) { - test.ok(project.objects['PBXTargetDependency']['301BF551109A68C00062928A']); - test.done(); -} - -exports['should have the right properties on the dependency'] = function (test) { - var dependency = project.objects['PBXTargetDependency']['301BF551109A68C00062928A']; - - test.equal(dependency.isa, 'PBXTargetDependency') - test.equal(dependency.name, 'PhoneGapLib') - test.equal(dependency.targetProxy, '301BF550109A68C00062928A') - test.equal(dependency['targetProxy_comment'], 'PBXContainerItemProxy') - - test.done(); -} - -exports['should merge two PBXTargetDependency sections'] = function (test) { - test.ok(project.objects['PBXTargetDependency']['301BF551109A68C00062928A']); - test.ok(project.objects['PBXTargetDependency']['45FDD1944D304A9F96DF3AC6']); - test.done(); -} - +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); +const assert = require('assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/section-split.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/section-split', () => { + it('should have a PBXTargetDependency section', () => { + assert.ok(project.objects.PBXTargetDependency); + }); + + it('should have the right child of PBXTargetDependency section', () => { + assert.ok(project.objects.PBXTargetDependency['301BF551109A68C00062928A']); + }); + + it('should have the right properties on the dependency', () => { + const dependency = project.objects.PBXTargetDependency['301BF551109A68C00062928A']; + + assert.strictEqual(dependency.isa, 'PBXTargetDependency'); + assert.strictEqual(dependency.name, 'PhoneGapLib'); + assert.strictEqual(dependency.targetProxy, '301BF550109A68C00062928A'); + assert.strictEqual(dependency.targetProxy_comment, 'PBXContainerItemProxy'); + }); + + it('should merge two PBXTargetDependency sections', () => { + assert.ok(project.objects.PBXTargetDependency['301BF551109A68C00062928A']); + assert.ok(project.objects.PBXTargetDependency['45FDD1944D304A9F96DF3AC6']); + }); +}); diff --git a/test/parser/section.js b/test/parser/section.js index 65e65fa2..7ec69c58 100644 --- a/test/parser/section.js +++ b/test/parser/section.js @@ -1,45 +1,48 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/section.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; - -exports['should have a PBXTargetDependency section'] = function (test) { - test.ok(project.objects['PBXTargetDependency']); - test.done(); -} - -exports['should have the right child of PBXTargetDependency section'] = function (test) { - test.ok(project.objects['PBXTargetDependency']['301BF551109A68C00062928A']); - test.done(); -} - -exports['should have the right properties on the dependency'] = function (test) { - var dependency = project.objects['PBXTargetDependency']['301BF551109A68C00062928A']; - - test.equal(dependency.isa, 'PBXTargetDependency') - test.equal(dependency.name, 'PhoneGapLib') - test.equal(dependency.targetProxy, '301BF550109A68C00062928A') - test.equal(dependency['targetProxy_comment'], 'PBXContainerItemProxy') - - test.done(); -} +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); +const assert = require('assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/section.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/section', () => { + it('should have a PBXTargetDependency section', () => { + assert.ok(project.objects.PBXTargetDependency); + }); + + it('should have the right child of PBXTargetDependency section', () => { + assert.ok(project.objects.PBXTargetDependency['301BF551109A68C00062928A']); + }); + + it('should have the right properties on the dependency', () => { + const dependency = project.objects.PBXTargetDependency['301BF551109A68C00062928A']; + + assert.strictEqual(dependency.isa, 'PBXTargetDependency'); + assert.strictEqual(dependency.name, 'PhoneGapLib'); + assert.strictEqual(dependency.targetProxy, '301BF550109A68C00062928A'); + assert.strictEqual(dependency.targetProxy_comment, 'PBXContainerItemProxy'); + }); +}); diff --git a/test/parser/two-sections.js b/test/parser/two-sections.js index 3f8e1f40..77f6fec1 100644 --- a/test/parser/two-sections.js +++ b/test/parser/two-sections.js @@ -1,35 +1,40 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/two-sections.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; + http://www.apache.org/licenses/LICENSE-2.0 -exports['should parse a project with two sections'] = function (test) { - // if it gets this far it's worked - test.done(); -} + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ -exports['should have both sections on the project object'] = function (test) { - test.ok(project.objects['PBXTargetDependency']); - test.ok(project.objects['PBXSourcesBuildPhase']); - test.done(); -} +const { describe, it } = require('node:test'); +const assert = require('assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/two-sections.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/two-sections', () => { + it('should parse a project with two sections', () => { + // if it gets this far it's worked + }); + + it('should have both sections on the project object', () => { + assert.ok(project.objects.PBXTargetDependency); + assert.ok(project.objects.PBXSourcesBuildPhase); + }); +}); diff --git a/test/parser/with_array.js b/test/parser/with_array.js index b63ef505..c87479d3 100644 --- a/test/parser/with_array.js +++ b/test/parser/with_array.js @@ -1,56 +1,58 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var PEG = require('pegjs'), - fs = require('fs'), - pbx = fs.readFileSync('test/parser/projects/with_array.pbxproj', 'utf-8'), - grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'), - parser = PEG.generate(grammar), - rawProj = parser.parse(pbx), - project = rawProj.project; - -exports['should parse arrays with commented entries'] = function (test) { - test.ok(project.files instanceof Array); - test.equal(project.files.length, 2); - test.done() -} - -exports['should parse arrays with uncommented entries'] = function (test) { - test.ok(project.ARCHS instanceof Array); - test.equal(project.ARCHS.length, 2); - test.done() -} - -exports['should parse empty arrays'] = function (test) { - test.ok(project.empties instanceof Array); - test.equal(project.empties.length, 0); - test.done(); -} - -exports['should be correct ordered'] = function (test) { - var archs = project.ARCHS; - test.equal(archs[0], 'armv6'); - test.equal(archs[1], 'armv7'); - test.done(); -} - -exports['should parse values and comments correctly'] = function (test) { - var appDelegate = project.files[1] - test.equal(appDelegate.value, '1D3623260D0F684500981E51') - test.equal(appDelegate.comment, 'AppDelegate.m in Sources') - test.done() -} +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); +const assert = require('assert'); + +const PEG = require('pegjs'); +const fs = require('fs'); +const pbx = fs.readFileSync('test/parser/projects/with_array.pbxproj', 'utf-8'); +const grammar = fs.readFileSync('lib/parser/pbxproj.pegjs', 'utf-8'); +const parser = PEG.generate(grammar); +const rawProj = parser.parse(pbx); +const project = rawProj.project; + +describe('parser/with_array', () => { + it('should parse arrays with commented entries', () => { + assert.ok(project.files instanceof Array); + assert.strictEqual(project.files.length, 2); + }); + + it('should parse arrays with uncommented entries', () => { + assert.ok(project.ARCHS instanceof Array); + assert.strictEqual(project.ARCHS.length, 2); + }); + + it('should parse empty arrays', () => { + assert.ok(project.empties instanceof Array); + assert.strictEqual(project.empties.length, 0); + }); + + it('should be correct ordered', () => { + const archs = project.ARCHS; + assert.strictEqual(archs[0], 'armv6'); + assert.strictEqual(archs[1], 'armv7'); + }); + + it('should parse values and comments correctly', () => { + const appDelegate = project.files[1]; + assert.strictEqual(appDelegate.value, '1D3623260D0F684500981E51'); + assert.strictEqual(appDelegate.comment, 'AppDelegate.m in Sources'); + }); +}); diff --git a/test/pbxCreateGroupWithType.js b/test/pbxCreateGroupWithType.js new file mode 100644 index 00000000..c168ca7f --- /dev/null +++ b/test/pbxCreateGroupWithType.js @@ -0,0 +1,49 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const PBXProject = require('../lib/pbxProject'); +let project; + +describe('pbxCreateGroupWithType', () => { + beforeEach(() => { + project = new PBXProject('test/parser/projects/group.pbxproj'); + project.parseSync(); + }); + + it('should not throw error when a non-restricted value is used as a group type.', () => { + assert.doesNotThrow( + () => { + project.pbxCreateGroupWithType('name', '.', 'FooBar'); + }, + /Error: "FooBar" is restricted and cannot be used as a group type\./ + ); + }); + + it('should throw error when a restricted value was passed in as a group type.', () => { + assert.throws( + () => { + project.pbxCreateGroupWithType('name', '.', 'prototype'); + }, + /Error: "prototype" is restricted and cannot be used as a group type\./ + ); + }); +}); diff --git a/test/pbxFile.js b/test/pbxFile.js index 4f0d1a2f..863dcac0 100644 --- a/test/pbxFile.js +++ b/test/pbxFile.js @@ -1,290 +1,266 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var pbxFile = require('../lib/pbxFile'); - -exports['lastKnownFileType'] = { - 'should detect that a .m path means sourcecode.c.objc': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.m'); - - test.equal('sourcecode.c.objc', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should detect that a .h path means sourceFile.c.h': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.h'); - - test.equal('sourcecode.c.h', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should detect that a .bundle path means "wrapper.plug-in"': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.bundle'); - - test.equal('wrapper.plug-in', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should detect that a .xib path means file.xib': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.xib'); - - test.equal('file.xib', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should detect that a .dylib path means "compiled.mach-o.dylib"': function (test) { - var sourceFile = new pbxFile('libsqlite3.dylib'); - - test.equal('compiled.mach-o.dylib', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should detect that a .tbd path means sourcecode.text-based-dylib-definition': function (test) { - var sourceFile = new pbxFile('libsqlite3.tbd'); - - test.equal('sourcecode.text-based-dylib-definition', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should detect that a .framework path means wrapper.framework': function (test) { - var sourceFile = new pbxFile('MessageUI.framework'); - - test.equal('wrapper.framework', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should detect that a .a path means archive.ar': function (test) { - var sourceFile = new pbxFile('libGoogleAnalytics.a'); - - test.equal('archive.ar', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should detect that a .xcdatamodel path means wrapper.xcdatamodel': function (test) { - var sourceFile = new pbxFile('dataModel.xcdatamodel'); - - test.equal('wrapper.xcdatamodel', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should allow lastKnownFileType to be overridden': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.m', +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); +const assert = require('node:assert'); + +const PBXFile = require('../lib/pbxFile'); + +describe('PBXFile', () => { + describe('lastKnownFileType', () => { + it('should detect that a .m path means sourcecode.c.objc', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.m'); + + assert.equal('sourcecode.c.objc', sourceFile.lastKnownFileType); + }); + + it('should detect that a .h path means sourceFile.c.h', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.h'); + + assert.equal('sourcecode.c.h', sourceFile.lastKnownFileType); + }); + + it('should detect that a .bundle path means "wrapper.plug-in"', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.bundle'); + + assert.equal('wrapper.plug-in', sourceFile.lastKnownFileType); + }); + + it('should detect that a .xib path means file.xib', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.xib'); + + assert.equal('file.xib', sourceFile.lastKnownFileType); + }); + + it('should detect that a .dylib path means "compiled.mach-o.dylib"', () => { + const sourceFile = new PBXFile('libsqlite3.dylib'); + + assert.equal('compiled.mach-o.dylib', sourceFile.lastKnownFileType); + }); + + it('should detect that a .tbd path means sourcecode.text-based-dylib-definition', () => { + const sourceFile = new PBXFile('libsqlite3.tbd'); + + assert.equal('sourcecode.text-based-dylib-definition', sourceFile.lastKnownFileType); + }); + + it('should detect that a .framework path means wrapper.framework', () => { + const sourceFile = new PBXFile('MessageUI.framework'); + + assert.equal('wrapper.framework', sourceFile.lastKnownFileType); + }); + + it('should detect that a .a path means archive.ar', () => { + const sourceFile = new PBXFile('libGoogleAnalytics.a'); + + assert.equal('archive.ar', sourceFile.lastKnownFileType); + }); + + it('should detect that a .xcdatamodel path means wrapper.xcdatamodel', () => { + const sourceFile = new PBXFile('dataModel.xcdatamodel'); + + assert.equal('wrapper.xcdatamodel', sourceFile.lastKnownFileType); + }); + + it('should allow lastKnownFileType to be overridden', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.m', { lastKnownFileType: 'somestupidtype' }); - test.equal('somestupidtype', sourceFile.lastKnownFileType); - test.done(); - }, - - 'should set lastKnownFileType to unknown if undetectable': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.guh'); - - test.equal('unknown', sourceFile.lastKnownFileType); - test.done(); - } -} - -exports['group'] = { - 'should be Sources for source files': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.m'); - - test.equal('Sources', sourceFile.group); - test.done(); - }, - 'should be Sources for data model document files': function (test) { - var dataModelFile = new pbxFile('dataModel.xcdatamodeld'); - - test.equal('Sources', dataModelFile.group); - test.done(); - }, - 'should be Frameworks for dylibs': function (test) { - var framework = new pbxFile('libsqlite3.dylib'); - - test.equal('Frameworks', framework.group); - test.done(); - }, - 'should be Frameworks for tbds': function (test) { - var framework = new pbxFile('libsqlite3.tbd'); - - test.equal('Frameworks', framework.group); - test.done(); - }, - 'should be Frameworks for frameworks': function (test) { - var framework = new pbxFile('MessageUI.framework'); - - test.equal('Frameworks', framework.group); - test.done(); - }, - 'should be Resources for all other files': function (test) { - var headerFile = new pbxFile('Plugins/ChildBrowser.h'), - xibFile = new pbxFile('Plugins/ChildBrowser.xib'); - - test.equal('Resources', headerFile.group); - test.equal('Resources', xibFile.group); - test.done(); - }, - 'should be Frameworks for archives': function (test) { - var archive = new pbxFile('libGoogleAnalytics.a'); - - test.equal('Frameworks', archive.group); - test.done(); - } -} - -exports['basename'] = { - 'should be as expected': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.m'); - - test.equal('ChildBrowser.m', sourceFile.basename); - test.done(); - } -} - -exports['sourceTree'] = { - 'should be SDKROOT for dylibs': function (test) { - var sourceFile = new pbxFile('libsqlite3.dylib'); - - test.equal('SDKROOT', sourceFile.sourceTree); - test.done(); - }, - - 'should be SDKROOT for tbds': function (test) { - var sourceFile = new pbxFile('libsqlite3.tbd'); - - test.equal('SDKROOT', sourceFile.sourceTree); - test.done(); - }, - - 'should be SDKROOT for frameworks': function (test) { - var sourceFile = new pbxFile('MessageUI.framework'); - - test.equal('SDKROOT', sourceFile.sourceTree); - test.done(); - }, - - 'should default to "" otherwise': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.m'); - - test.equal('""', sourceFile.sourceTree); - test.done(); - }, - - 'should be overridable either way': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.m', - { sourceTree: 'SOMETHING'}); - - test.equal('SOMETHING', sourceFile.sourceTree); - test.done(); - }, - - 'should be "" for archives': function (test) { - var archive = new pbxFile('libGoogleAnalytics.a'); - - test.equal('""', archive.sourceTree); - test.done(); - } -} - -exports['path'] = { - 'should be "usr/lib" for dylibs (relative to SDKROOT)': function (test) { - var sourceFile = new pbxFile('libsqlite3.dylib'); - - test.equal('usr/lib/libsqlite3.dylib', sourceFile.path); - test.done(); - }, - - 'should be "usr/lib" for tbds (relative to SDKROOT)': function (test) { - var sourceFile = new pbxFile('libsqlite3.tbd'); - - test.equal('usr/lib/libsqlite3.tbd', sourceFile.path); - test.done(); - }, - - 'should be "System/Library/Frameworks" for frameworks': function (test) { - var sourceFile = new pbxFile('MessageUI.framework'); - - test.equal('System/Library/Frameworks/MessageUI.framework', sourceFile.path); - test.done(); - }, - - - 'should default to the first argument otherwise': function (test) { - var sourceFile = new pbxFile('Plugins/ChildBrowser.m'); - - test.equal('Plugins/ChildBrowser.m', sourceFile.path); - test.done(); - } -} - -exports['settings'] = { - 'should not be defined by default': function (test) { - var sourceFile = new pbxFile('social.framework'); - - test.equal(undefined, sourceFile.settings); - test.done(); - }, + assert.equal('somestupidtype', sourceFile.lastKnownFileType); + }); + + it('should set lastKnownFileType to unknown if undetectable', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.guh'); + + assert.equal('unknown', sourceFile.lastKnownFileType); + }); + }); + + describe('group', () => { + it('should be Sources for source files', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.m'); + + assert.equal('Sources', sourceFile.group); + }); + + it('should be Sources for data model document files', () => { + const dataModelFile = new PBXFile('dataModel.xcdatamodeld'); + + assert.equal('Sources', dataModelFile.group); + }); + + it('should be Frameworks for dylibs', () => { + const framework = new PBXFile('libsqlite3.dylib'); + + assert.equal('Frameworks', framework.group); + }); + + it('should be Frameworks for tbds', () => { + const framework = new PBXFile('libsqlite3.tbd'); + + assert.equal('Frameworks', framework.group); + }); + + it('should be Frameworks for frameworks', () => { + const framework = new PBXFile('MessageUI.framework'); + + assert.equal('Frameworks', framework.group); + }); + + it('should be Resources for all other files', () => { + const headerFile = new PBXFile('Plugins/ChildBrowser.h'); + const xibFile = new PBXFile('Plugins/ChildBrowser.xib'); + + assert.equal('Resources', headerFile.group); + assert.equal('Resources', xibFile.group); + }); + + it('should be Frameworks for archives', () => { + const archive = new PBXFile('libGoogleAnalytics.a'); + + assert.equal('Frameworks', archive.group); + }); + }); + + describe('basename', () => { + it('should be as expected', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.m'); + + assert.equal('ChildBrowser.m', sourceFile.basename); + }); + }); + + describe('sourceTree', () => { + it('should be SDKROOT for dylibs', () => { + const sourceFile = new PBXFile('libsqlite3.dylib'); + + assert.equal('SDKROOT', sourceFile.sourceTree); + }); + + it('should be SDKROOT for tbds', () => { + const sourceFile = new PBXFile('libsqlite3.tbd'); + + assert.equal('SDKROOT', sourceFile.sourceTree); + }); + + it('should be SDKROOT for frameworks', () => { + const sourceFile = new PBXFile('MessageUI.framework'); + + assert.equal('SDKROOT', sourceFile.sourceTree); + }); + + it('should default to "" otherwise', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.m'); + + assert.equal('""', sourceFile.sourceTree); + }); + + it('should be overridable either way', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.m', + { sourceTree: 'SOMETHING' }); + + assert.equal('SOMETHING', sourceFile.sourceTree); + }); + + it('should be "" for archives', () => { + const archive = new PBXFile('libGoogleAnalytics.a'); + + assert.equal('""', archive.sourceTree); + }); + }); + + describe('path', () => { + it('should be "usr/lib" for dylibs (relative to SDKROOT)', () => { + const sourceFile = new PBXFile('libsqlite3.dylib'); + + assert.equal('usr/lib/libsqlite3.dylib', sourceFile.path); + }); + + it('should be "usr/lib" for tbds (relative to SDKROOT)', () => { + const sourceFile = new PBXFile('libsqlite3.tbd'); + + assert.equal('usr/lib/libsqlite3.tbd', sourceFile.path); + }); + + it('should be "System/Library/Frameworks" for frameworks', () => { + const sourceFile = new PBXFile('MessageUI.framework'); + + assert.equal('System/Library/Frameworks/MessageUI.framework', sourceFile.path); + }); + + it('should default to the first argument otherwise', () => { + const sourceFile = new PBXFile('Plugins/ChildBrowser.m'); + + assert.equal('Plugins/ChildBrowser.m', sourceFile.path); + }); + }); + + describe('settings', () => { + it('should not be defined by default', () => { + const sourceFile = new PBXFile('social.framework'); + + assert.equal(undefined, sourceFile.settings); + }); - 'should be undefined if weak is false or non-boolean': function (test) { - var sourceFile1 = new pbxFile('social.framework', - { weak: false }); - var sourceFile2 = new pbxFile('social.framework', - { weak: 'bad_value' }); + it('should be undefined if weak is false or non-boolean', () => { + const sourceFile1 = new PBXFile('social.framework', + { weak: false }); + const sourceFile2 = new PBXFile('social.framework', + { weak: 'bad_value' }); - test.equal(undefined, sourceFile1.settings); - test.equal(undefined, sourceFile2.settings); - test.done(); - }, + assert.equal(undefined, sourceFile1.settings); + assert.equal(undefined, sourceFile2.settings); + }); - 'should be {ATTRIBUTES:["Weak"]} if weak linking specified': function (test) { - var sourceFile = new pbxFile('social.framework', - { weak: true }); + it('should be {ATTRIBUTES:["Weak"]} if weak linking specified', () => { + const sourceFile = new PBXFile('social.framework', + { weak: true }); - test.deepEqual({ATTRIBUTES:["Weak"]}, sourceFile.settings); - test.done(); - }, + assert.deepEqual({ ATTRIBUTES: ['Weak'] }, sourceFile.settings); + }); - 'should be {ATTRIBUTES:["CodeSignOnCopy"]} if sign specified': function (test) { - var sourceFile = new pbxFile('signable.framework', - { embed: true, sign: true }); + it('should be {ATTRIBUTES:["CodeSignOnCopy"]} if sign specified', () => { + const sourceFile = new PBXFile('signable.framework', + { embed: true, sign: true }); - test.deepEqual({ATTRIBUTES:["CodeSignOnCopy"]}, sourceFile.settings); - test.done(); - }, + assert.deepEqual({ ATTRIBUTES: ['CodeSignOnCopy'] }, sourceFile.settings); + }); - 'should be {ATTRIBUTES:["Weak","CodeSignOnCopy"]} if both weak linking and sign specified': function (test) { - var sourceFile = new pbxFile('signableWeak.framework', - { embed: true, weak: true, sign: true }); + it('should be {ATTRIBUTES:["Weak","CodeSignOnCopy"]} if both weak linking and sign specified', () => { + const sourceFile = new PBXFile('signableWeak.framework', + { embed: true, weak: true, sign: true }); - test.deepEqual({ATTRIBUTES:["Weak", "CodeSignOnCopy"]}, sourceFile.settings); - test.done(); - }, + assert.deepEqual({ ATTRIBUTES: ['Weak', 'CodeSignOnCopy'] }, sourceFile.settings); + }); - 'should be {COMPILER_FLAGS:"blah"} if compiler flags specified': function (test) { - var sourceFile = new pbxFile('Plugins/BarcodeScanner.m', - { compilerFlags: "-std=c++11 -fno-objc-arc" }); + it('should be {COMPILER_FLAGS:"blah"} if compiler flags specified', () => { + const sourceFile = new PBXFile('Plugins/BarcodeScanner.m', + { compilerFlags: '-std=c++11 -fno-objc-arc' }); - test.deepEqual({COMPILER_FLAGS:'"-std=c++11 -fno-objc-arc"'}, sourceFile.settings); - test.done(); - }, + assert.deepEqual({ COMPILER_FLAGS: '"-std=c++11 -fno-objc-arc"' }, sourceFile.settings); + }); - 'should be .appex if {explicitFileType:\'"wrapper.app-extension"\'} specified': function (test) { - var sourceFile = new pbxFile('AppExtension', - { explicitFileType: '"wrapper.app-extension"'}); + it('should be .appex if {explicitFileType:\'"wrapper.app-extension"\'} specified', () => { + const sourceFile = new PBXFile('AppExtension', + { explicitFileType: '"wrapper.app-extension"' }); - test.equal('AppExtension.appex', sourceFile.basename); - test.done(); - } -} + assert.equal('AppExtension.appex', sourceFile.basename); + }); + }); +}); diff --git a/test/pbxItemByComment.js b/test/pbxItemByComment.js index 5bee287c..f1b95a4c 100644 --- a/test/pbxItemByComment.js +++ b/test/pbxItemByComment.js @@ -1,67 +1,69 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - proj = new pbx('.'); + http://www.apache.org/licenses/LICENSE-2.0 -function cleanHash() { + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('pbxItemByComment', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.pbxItemByComment = { - 'should return PBXTargetDependency': function (test) { - var pbxItem = proj.pbxItemByComment('PBXTargetDependency', 'PBXTargetDependency'); + it('should return PBXTargetDependency', () => { + const pbxItem = proj.pbxItemByComment('PBXTargetDependency', 'PBXTargetDependency'); - test.ok(pbxItem); - test.equals(pbxItem.isa, 'PBXTargetDependency'); - test.done() - }, - 'should return PBXContainerItemProxy': function (test) { - var pbxItem = proj.pbxItemByComment('libPhoneGap.a', 'PBXReferenceProxy'); + assert.ok(pbxItem); + assert.equal(pbxItem.isa, 'PBXTargetDependency'); + }); - test.ok(pbxItem); - test.equals(pbxItem.isa, 'PBXReferenceProxy'); - test.done() - }, - 'should return PBXResourcesBuildPhase': function (test) { - var pbxItem = proj.pbxItemByComment('Resources', 'PBXResourcesBuildPhase'); + it('should return PBXContainerItemProxy', () => { + const pbxItem = proj.pbxItemByComment('libPhoneGap.a', 'PBXReferenceProxy'); - test.ok(pbxItem); - test.equals(pbxItem.isa, 'PBXResourcesBuildPhase'); - test.done() - }, - 'should return PBXShellScriptBuildPhase': function (test) { - var pbxItem = proj.pbxItemByComment('Touch www folder', 'PBXShellScriptBuildPhase'); + assert.ok(pbxItem); + assert.equal(pbxItem.isa, 'PBXReferenceProxy'); + }); - test.ok(pbxItem); - test.equals(pbxItem.isa, 'PBXShellScriptBuildPhase'); - test.done() - }, - 'should return null when PBXNativeTarget not found': function (test) { - var pbxItem = proj.pbxItemByComment('Invalid', 'PBXTargetDependency'); + it('should return PBXResourcesBuildPhase', () => { + const pbxItem = proj.pbxItemByComment('Resources', 'PBXResourcesBuildPhase'); - test.equal(pbxItem, null); - test.done() - } -} + assert.ok(pbxItem); + assert.equal(pbxItem.isa, 'PBXResourcesBuildPhase'); + }); + + it('should return PBXShellScriptBuildPhase', () => { + const pbxItem = proj.pbxItemByComment('Touch www folder', 'PBXShellScriptBuildPhase'); + + assert.ok(pbxItem); + assert.equal(pbxItem.isa, 'PBXShellScriptBuildPhase'); + }); + + it('should return null when PBXNativeTarget not found', () => { + const pbxItem = proj.pbxItemByComment('Invalid', 'PBXTargetDependency'); + + assert.equal(pbxItem, null); + }); +}); diff --git a/test/pbxProject.js b/test/pbxProject.js index c076b96b..2b62a247 100644 --- a/test/pbxProject.js +++ b/test/pbxProject.js @@ -1,330 +1,351 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var pbx = require('../lib/pbxProject'), - buildConfig = require('./fixtures/buildFiles'), - jsonProject = require('./fixtures/full-project'), - fs = require('fs'), - project; - -exports['creation'] = { - 'should create a pbxProject with the new operator': function (test) { - var myProj = new pbx('test/parser/projects/hash.pbxproj'); - - test.ok(myProj instanceof pbx); - test.done(); - }, - 'should create a pbxProject without the new operator': function (test) { - var myProj = pbx('test/parser/projects/hash.pbxproj'); - - test.ok(myProj instanceof pbx); - test.done(); - } -} - -exports['parseSync function'] = { - 'should return the hash object': function (test) { - var myProj = new pbx('test/parser/projects/hash.pbxproj') - , projHash = myProj.parseSync(); - test.ok(projHash); - test.done(); - }, - 'should contain valid data in the returned objects hash': function (test) { - var myProj = new pbx('test/parser/projects/hash.pbxproj') - , projHash = myProj.parseSync(); - test.ok(projHash); - - test.equal(projHash.hash.project.archiveVersion, 1); - test.equal(projHash.hash.project.objectVersion, 45); - test.equal(projHash.hash.project.nonObject, '29B97313FDCFA39411CA2CEF'); - - test.done(); - }, -} - -exports['parse function'] = { - 'should emit an "end" event': function (test) { - var myProj = new pbx('test/parser/projects/hash.pbxproj'); - - myProj.parse().on('end', function (err, projHash) { - test.done(); - }) - }, - 'should take the end callback as a parameter': function (test) { - var myProj = new pbx('test/parser/projects/hash.pbxproj'); - - myProj.parse(function (err, projHash) { - test.done(); - }) - }, - 'should allow evented error handling': function (test) { - var myProj = new pbx('NotARealPath.pbxproj'); - - myProj.parse().on('error', function (err) { - test.equal(typeof err, "object"); - test.done(); - }) - }, - 'should pass the hash object to the callback function': function (test) { - var myProj = new pbx('test/parser/projects/hash.pbxproj'); - - myProj.parse(function (err, projHash) { - test.ok(projHash); - test.done(); - }) - }, - 'should handle projects with comments in the header': function (test) { - var myProj = new pbx('test/parser/projects/comments.pbxproj'); - - myProj.parse(function (err, projHash) { - test.ok(projHash); - test.done(); - }) - }, - 'should attach the hash object to the pbx object': function (test) { - var myProj = new pbx('test/parser/projects/hash.pbxproj'); - - myProj.parse(function (err, projHash) { - test.ok(myProj.hash); - test.done(); - }) - }, - 'it should pass an error object back when the parsing fails': function (test) { - var myProj = new pbx('test/parser/projects/fail.pbxproj'); - - myProj.parse(function (err, projHash) { - test.ok(err); - test.done(); - }) - } -} - -exports['allUuids function'] = { - 'should return the right amount of uuids': function (test) { - var project = new pbx('.'), - uuids; - - project.hash = buildConfig; - uuids = project.allUuids(); - - test.equal(uuids.length, 4); - test.done(); - } -} - -exports['generateUuid function'] = { - 'should return a 24 character string': function (test) { - var project = new pbx('.'), - newUUID; - - project.hash = buildConfig; - newUUID = project.generateUuid(); - - test.equal(newUUID.length, 24); - test.done(); - }, - 'should be an uppercase hex string': function (test) { - var project = new pbx('.'), - uHex = /^[A-F0-9]{24}$/, - newUUID; - - project.hash = buildConfig; - newUUID = project.generateUuid(); - - test.ok(uHex.test(newUUID)); - test.done(); - } -} - -var bcpbx = 'test/parser/projects/build-config.pbxproj'; -var original_pbx = fs.readFileSync(bcpbx, 'utf-8'); - -exports['updateProductName function'] = { - setUp:function(callback) { - callback(); - }, - tearDown:function(callback) { - fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); - callback(); - }, - 'should change the PRODUCT_NAME field in the .pbxproj file': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.updateProductName('furious anger'); - var newContents = myProj.writeSync(); - test.ok(newContents.match(/PRODUCT_NAME\s*=\s*"furious anger"/)); - test.done(); - }); - } -} - -exports['updateBuildProperty function'] = { - setUp:function(callback) { - callback(); - }, - tearDown:function(callback) { - fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); - callback(); - }, - 'should change build properties in the .pbxproj file': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.updateBuildProperty('TARGETED_DEVICE_FAMILY', '"arm"'); - var newContents = myProj.writeSync(); - test.ok(newContents.match(/TARGETED_DEVICE_FAMILY\s*=\s*"arm"/)); - myProj.updateBuildProperty('OTHER_LDFLAGS', ['T','E','S','T']); - newContents = myProj.writeSync(); - test.ok(newContents.match(/OTHER_LDFLAGS\s*=\s*\(\s*T,\s*E,\s*S,\s*T,\s*\)/)) - test.done(); - }); - } -} - -exports['addBuildProperty function'] = { - setUp:function(callback) { - callback(); - }, - tearDown:function(callback) { - fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); - callback(); - }, - 'should add 4 build properties in the .pbxproj file': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.addBuildProperty('ENABLE_BITCODE', 'NO'); - var newContents = myProj.writeSync(); - test.equal(newContents.match(/ENABLE_BITCODE\s*=\s*NO/g).length, 4); - test.done(); - }); - }, - 'should add 2 build properties in the .pbxproj file for specific build': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.addBuildProperty('ENABLE_BITCODE', 'NO', 'Release'); - var newContents = myProj.writeSync(); - test.equal(newContents.match(/ENABLE_BITCODE\s*=\s*NO/g).length, 2); - test.done(); - }); - }, - 'should not add build properties in the .pbxproj file for nonexist build': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.addBuildProperty('ENABLE_BITCODE', 'NO', 'nonexist'); - var newContents = myProj.writeSync(); - test.ok(!newContents.match(/ENABLE_BITCODE\s*=\s*NO/g)); - test.done(); - }); - } -} - -exports['removeBuildProperty function'] = { - setUp:function(callback) { - callback(); - }, - tearDown:function(callback) { - fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); - callback(); - }, - 'should remove all build properties in the .pbxproj file': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.removeBuildProperty('IPHONEOS_DEPLOYMENT_TARGET'); - var newContents = myProj.writeSync(); - test.ok(!newContents.match(/IPHONEOS_DEPLOYMENT_TARGET/)); - test.done(); - }); - }, - 'should remove specific build properties in the .pbxproj file': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.removeBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', 'Debug'); - var newContents = myProj.writeSync(); - test.equal(newContents.match(/IPHONEOS_DEPLOYMENT_TARGET/g).length, 2); - test.done(); - }); - }, - 'should not remove any build properties in the .pbxproj file': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.removeBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', 'notexist'); - var newContents = myProj.writeSync(); - test.equal(newContents.match(/IPHONEOS_DEPLOYMENT_TARGET/g).length, 4); - test.done(); - }); - }, - 'should fine with remove inexist build properties in the .pbxproj file': function (test) { - var myProj = new pbx('test/parser/projects/build-config.pbxproj'); - myProj.parse(function(err, hash) { - myProj.removeBuildProperty('ENABLE_BITCODE'); - var newContents = myProj.writeSync(); - test.ok(!newContents.match(/ENABLE_BITCODE/)); - test.done(); - }); - } - -} - -exports['productName field'] = { - 'should return the product name': function (test) { - var newProj = new pbx('.'); - newProj.hash = jsonProject; - - test.equal(newProj.productName, 'KitchenSinktablet'); - test.done(); - } -} - -exports['addPluginFile function'] = { - 'should strip the Plugin path prefix': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj'); - - myProj.parse(function (err, hash) { - test.equal(myProj.addPluginFile('Plugins/testMac.m').path, 'testMac.m'); - test.equal(myProj.addPluginFile('Plugins\\testWin.m').path, 'testWin.m'); - test.done(); - }); - }, - 'should add files to the .pbxproj file using the / path seperator': function (test) { - var myProj = new pbx('test/parser/projects/full.pbxproj'); - - myProj.parse(function (err, hash) { - var file = myProj.addPluginFile('myPlugin\\newFile.m'); - - test.equal(myProj.pbxFileReferenceSection()[file.fileRef].path, '"myPlugin/newFile.m"'); - test.done(); - }); - } -} - -exports['hasFile'] = { - 'should return true if the file is in the project': function (test) { - var newProj = new pbx('.'); - newProj.hash = jsonProject; - - // sourceTree: '""' - test.ok(newProj.hasFile('AppDelegate.m')) - test.done() - }, - 'should return false if the file is not in the project': function (test) { - var newProj = new pbx('.'); - newProj.hash = jsonProject; - - // sourceTree: '""' - test.ok(!newProj.hasFile('NotTheAppDelegate.m')) - test.done() - } -} +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, afterEach } = require('node:test'); +const assert = require('node:assert'); + +const PBXProject = require('../lib/pbxProject'); +const buildConfig = require('./fixtures/buildFiles'); +const jsonProject = require('./fixtures/full-project'); +const fs = require('fs'); + +describe('PBXProject', () => { + describe('creation', () => { + it('should create a pbxProject with the new operator', () => { + const myProj = new PBXProject('test/parser/projects/hash.pbxproj'); + + assert.ok(myProj instanceof PBXProject); + }); + + it('should create a pbxProject without the new operator', () => { + const myProj = PBXProject('test/parser/projects/hash.pbxproj'); + + assert.ok(myProj instanceof PBXProject); + }); + }); + + describe('parseSync function', () => { + it('should return the hash object', () => { + const myProj = new PBXProject('test/parser/projects/hash.pbxproj'); + const projHash = myProj.parseSync(); + assert.ok(projHash); + }); + it('should contain valid data in the returned objects hash', () => { + const myProj = new PBXProject('test/parser/projects/hash.pbxproj'); + const projHash = myProj.parseSync(); + assert.ok(projHash); + + assert.equal(projHash.hash.project.archiveVersion, 1); + assert.equal(projHash.hash.project.objectVersion, 45); + assert.equal(projHash.hash.project.nonObject, '29B97313FDCFA39411CA2CEF'); + }); + }); + + describe('parse function', () => { + it('should emit an "end" event', (t, done) => { + const myProj = new PBXProject('test/parser/projects/hash.pbxproj'); + + myProj.parse().on('end', function () { + done(); + }); + }); + it('should take the end callback as a parameter', (t, done) => { + const myProj = new PBXProject('test/parser/projects/hash.pbxproj'); + + myProj.parse(function () { + done(); + }); + }); + it('should allow evented error handling', (t, done) => { + const myProj = new PBXProject('NotARealPath.pbxproj'); + + myProj.parse().on('error', function (err) { + assert.equal(typeof err, 'object'); + done(); + }); + }); + it('should pass the hash object to the callback function', (t, done) => { + const myProj = new PBXProject('test/parser/projects/hash.pbxproj'); + + myProj.parse(function (_, projHash) { + assert.ok(projHash); + done(); + }); + }); + it('should handle projects with comments in the header', (t, done) => { + const myProj = new PBXProject('test/parser/projects/comments.pbxproj'); + + myProj.parse(function (_, projHash) { + assert.ok(projHash); + done(); + }); + }); + it('should attach the hash object to the pbx object', (t, done) => { + const myProj = new PBXProject('test/parser/projects/hash.pbxproj'); + + myProj.parse(function () { + assert.ok(myProj.hash); + done(); + }); + }); + it('it should pass an error object back when the parsing fails', (t, done) => { + const myProj = new PBXProject('test/parser/projects/fail.pbxproj'); + + myProj.parse(function (err, _) { + assert.ok(err); + done(); + }); + }); + }); + + describe('allUuids function', () => { + it('should return the right amount of uuids', () => { + const project = new PBXProject('.'); + + project.hash = buildConfig; + const uuids = project.allUuids(); + + assert.equal(uuids.length, 4); + }); + }); + + describe('generateUuid function', () => { + it('should return a 24 character string', () => { + const project = new PBXProject('.'); + + project.hash = buildConfig; + const newUUID = project.generateUuid(); + + assert.equal(newUUID.length, 24); + }); + it('should be an uppercase hex string', () => { + const project = new PBXProject('.'); + const uHex = /^[A-F0-9]{24}$/; + + project.hash = buildConfig; + const newUUID = project.generateUuid(); + + assert.ok(uHex.test(newUUID)); + }); + }); + + const bcpbx = 'test/parser/projects/build-config.pbxproj'; + const original_pbx = fs.readFileSync(bcpbx, 'utf-8'); + + describe('updateProductName function', () => { + afterEach(() => { + fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); + }); + it('should change the PRODUCT_NAME field in the .pbxproj file', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.updateProductName('furious anger'); + const newContents = myProj.writeSync(); + assert.ok(newContents.match(/PRODUCT_NAME\s*=\s*"furious anger"/)); + done(); + }); + }); + }); + + describe('updateBuildProperty function', () => { + afterEach(() => { + fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); + }); + it('should change build properties in the .pbxproj file', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.updateBuildProperty('TARGETED_DEVICE_FAMILY', '"arm"'); + let newContents = myProj.writeSync(); + assert.ok(newContents.match(/TARGETED_DEVICE_FAMILY\s*=\s*"arm"/)); + myProj.updateBuildProperty('OTHER_LDFLAGS', ['T', 'E', 'S', 'T']); + newContents = myProj.writeSync(); + assert.ok(newContents.match(/OTHER_LDFLAGS\s*=\s*\(\s*T,\s*E,\s*S,\s*T,\s*\)/)); + done(); + }); + }); + it('should change all targets in .pbxproj with multiple targets', (t, done) => { + const myProj = new PBXProject('test/parser/projects/multitarget.pbxproj'); + myProj.parse(function () { + myProj.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', 'comcompanytest'); + const newContents = myProj.writeSync(); + // Should be 10 times = 5 targets, debug and release each + assert.ok(newContents.match(/PRODUCT_BUNDLE_IDENTIFIER\s*=\s*comcompanytest/g).length === 10); + done(); + }); + }); + it('should change only one target in .pbxproj with multiple targets', (t, done) => { + const myProj = new PBXProject('test/parser/projects/multitarget.pbxproj'); + myProj.parse(function () { + myProj.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', 'comcompanytest', null, 'MultiTargetTest'); + const newContents = myProj.writeSync(); + // should be 2 times = one target debug and release + assert.ok(newContents.match(/PRODUCT_BUNDLE_IDENTIFIER\s*=\s*comcompanytest/g).length === 2); + done(); + }); + }); + }); + + describe('getBuildProperty function', () => { + afterEach(() => { + fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); + }); + it('should change all targets in .pbxproj with multiple targets', (t, done) => { + const myProj = new PBXProject('test/parser/projects/multitarget.pbxproj'); + myProj.parse(function () { + myProj.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', 'comcompanytest'); + myProj.writeSync(); + assert.ok(myProj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER') === 'comcompanytest'); + done(); + }); + }); + it('should change only one target in .pbxproj with multiple targets', (t, done) => { + const myProj = new PBXProject('test/parser/projects/multitarget.pbxproj'); + myProj.parse(function () { + myProj.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', 'comcompanytest', null, 'MultiTargetTest'); + myProj.writeSync(); + assert.ok(myProj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, 'MultiTargetTest') === 'comcompanytest'); + done(); + }); + }); + }); + + describe('addBuildProperty function', () => { + afterEach(() => { + fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); + }); + it('should add 4 build properties in the .pbxproj file', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.addBuildProperty('ENABLE_BITCODE', 'NO'); + const newContents = myProj.writeSync(); + assert.equal(newContents.match(/ENABLE_BITCODE\s*=\s*NO/g).length, 4); + done(); + }); + }); + it('should add 2 build properties in the .pbxproj file for specific build', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.addBuildProperty('ENABLE_BITCODE', 'NO', 'Release'); + const newContents = myProj.writeSync(); + assert.equal(newContents.match(/ENABLE_BITCODE\s*=\s*NO/g).length, 2); + done(); + }); + }); + it('should not add build properties in the .pbxproj file for nonexist build', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.addBuildProperty('ENABLE_BITCODE', 'NO', 'nonexist'); + const newContents = myProj.writeSync(); + assert.ok(!newContents.match(/ENABLE_BITCODE\s*=\s*NO/g)); + done(); + }); + }); + }); + + describe('removeBuildProperty function', () => { + afterEach(() => { + fs.writeFileSync(bcpbx, original_pbx, 'utf-8'); + }); + it('should remove all build properties in the .pbxproj file', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.removeBuildProperty('IPHONEOS_DEPLOYMENT_TARGET'); + const newContents = myProj.writeSync(); + assert.ok(!newContents.match(/IPHONEOS_DEPLOYMENT_TARGET/)); + done(); + }); + }); + it('should remove specific build properties in the .pbxproj file', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.removeBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', 'Debug'); + const newContents = myProj.writeSync(); + assert.equal(newContents.match(/IPHONEOS_DEPLOYMENT_TARGET/g).length, 2); + done(); + }); + }); + it('should not remove any build properties in the .pbxproj file', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.removeBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', 'notexist'); + const newContents = myProj.writeSync(); + assert.equal(newContents.match(/IPHONEOS_DEPLOYMENT_TARGET/g).length, 4); + done(); + }); + }); + it('should fine with remove inexist build properties in the .pbxproj file', (t, done) => { + const myProj = new PBXProject('test/parser/projects/build-config.pbxproj'); + myProj.parse(function () { + myProj.removeBuildProperty('ENABLE_BITCODE'); + const newContents = myProj.writeSync(); + assert.ok(!newContents.match(/ENABLE_BITCODE/)); + done(); + }); + }); + }); + + describe('productName field', () => { + it('should return the product name', () => { + const newProj = new PBXProject('.'); + newProj.hash = jsonProject; + + assert.equal(newProj.productName, 'KitchenSinktablet'); + }); + }); + + describe('addPluginFile function', () => { + it('should strip the Plugin path prefix', (t, done) => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj'); + + myProj.parse(function () { + assert.equal(myProj.addPluginFile('Plugins/testMac.m').path, 'testMac.m'); + assert.equal(myProj.addPluginFile('Plugins\\testWin.m').path, 'testWin.m'); + done(); + }); + }); + it('should add files to the .pbxproj file using the / path seperator', (t, done) => { + const myProj = new PBXProject('test/parser/projects/full.pbxproj'); + + myProj.parse(function () { + const file = myProj.addPluginFile('myPlugin\\newFile.m'); + + assert.equal(myProj.pbxFileReferenceSection()[file.fileRef].path, '"myPlugin/newFile.m"'); + done(); + }); + }); + }); + + describe('hasFile', () => { + it('should return true if the file is in the project', () => { + const newProj = new PBXProject('.'); + newProj.hash = jsonProject; + + // sourceTree: '""' + assert.ok(newProj.hasFile('AppDelegate.m')); + }); + + it('should return false if the file is not in the project', () => { + const newProj = new PBXProject('.'); + newProj.hash = jsonProject; + + // sourceTree: '""' + assert.ok(!newProj.hasFile('NotTheAppDelegate.m')); + }); + }); +}); diff --git a/test/pbxTargetByName.js b/test/pbxTargetByName.js index 15c956d0..d3278153 100644 --- a/test/pbxTargetByName.js +++ b/test/pbxTargetByName.js @@ -1,46 +1,49 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('pbxTargetByName', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.pbxTargetByName = { - 'should return PBXNativeTarget': function (test) { - var pbxTarget = proj.pbxTargetByName('KitchenSinktablet'); + it('should return PBXNativeTarget', () => { + const pbxTarget = proj.pbxTargetByName('KitchenSinktablet'); - test.ok(pbxTarget); - test.equals(pbxTarget.isa, 'PBXNativeTarget'); - test.done() - }, - 'should return null when PBXNativeTarget not found': function (test) { - var pbxTarget = proj.pbxTargetByName('Invalid'); + assert.ok(pbxTarget); + assert.equal(pbxTarget.isa, 'PBXNativeTarget'); + }); - test.equal(pbxTarget, null); - test.done() - } -} + it('should return null when PBXNativeTarget not found', () => { + const pbxTarget = proj.pbxTargetByName('Invalid'); + + assert.equal(pbxTarget, null); + }); +}); diff --git a/test/pbxWriter.js b/test/pbxWriter.js index f1e2ee40..611db981 100644 --- a/test/pbxWriter.js +++ b/test/pbxWriter.js @@ -1,132 +1,148 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var pbx = require('../lib/pbxProject'), - fs = require('fs'), - myProj; - -function testProjectContents(filename, test, expectedFilename) { - var myProj = new pbx(filename); - - var content; +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it } = require('node:test'); +const assert = require('node:assert'); + +const PBXProject = require('../lib/pbxProject'); +const fs = require('fs'); + +function testProjectContents (filename, expectedFilename) { + const myProj = new PBXProject(filename); + + let content; if (expectedFilename) { content = fs.readFileSync(expectedFilename, 'utf-8'); } else { content = fs.readFileSync(filename, 'utf-8'); } // normalize tabs vs strings - content = content.replace(/ /g, '\t'); - - myProj.parse(function (err, projHash) { - var written = myProj.writeSync(); + content = content.replace(/ {4}/g, '\t'); - test.equal(content, written); - test.done(); + return new Promise(function (resolve) { + myProj.parse(function () { + const written = myProj.writeSync(); + assert.equal(content, written); + resolve(); + }); }); } -// for debugging failing tests -function testContentsInDepth(filename, test) { - var myProj = new pbx(filename), - content = fs.readFileSync(filename, 'utf-8'); +// // for debugging failing tests +// function testContentsInDepth(filename) { +// var myProj = new PBXProject(filename), +// content = fs.readFileSync(filename, 'utf-8'); - // normalize tabs vs strings - content = content.replace(/ /g, '\t'); +// // normalize tabs vs strings +// content = content.replace(/ /g, '\t'); - myProj.parse(function (err, projHash) { - var written = myProj.writeSync(), - writtenLines = written.split('\n') - contentLines = content.split('\n') +// myProj.parse(function (err, projHash) { +// var written = myProj.writeSync(), +// writtenLines = written.split('\n') +// contentLines = content.split('\n') - test.equal(writtenLines.length, contentLines.length); +// assert.equal(writtenLines.length, contentLines.length); - for (var i=0; i { + it('should write out the "hash" test', () => { + testProjectContents('test/parser/projects/hash.pbxproj'); }); -} -exports.writeSync = { - 'should write out the "hash" test': function (test) { - testProjectContents('test/parser/projects/hash.pbxproj', test); - }, - 'should write out the "with_array" test': function (test) { + it('should write out the "with_array" test', () => { // Special case in that the originating project does not have a trailing comma for all of its array entries. // This is definitely possibly. // But when we write/read it out again during testing, the trailing commas are introduced by our library. - testProjectContents('test/parser/projects/with_array.pbxproj', test, 'test/parser/projects/expected/with_array_expected.pbxproj'); - }, - 'should write out the "section" test': function (test) { - testProjectContents('test/parser/projects/section.pbxproj', test); - }, - 'should write out the "two-sections" test': function (test) { - testProjectContents('test/parser/projects/two-sections.pbxproj', test); - }, - 'should write out the "section-entries" test': function (test) { - testProjectContents('test/parser/projects/section-entries.pbxproj', test); - }, - 'should write out the "build-config" test': function (test) { - testProjectContents('test/parser/projects/build-config.pbxproj', test); - }, - 'should write out the "header-search" test': function (test) { - testProjectContents('test/parser/projects/header-search.pbxproj', test); - }, - 'should write out the "nested-object" test': function (test) { - testProjectContents('test/parser/projects/nested-object.pbxproj', test); - }, - 'should write out the "build-files" test': function (test) { - testProjectContents('test/parser/projects/build-files.pbxproj', test); - }, - 'should write out the "file-references" test': function (test) { - testProjectContents('test/parser/projects/file-references.pbxproj', test); - }, - 'should not null and undefined with the "omitEmptyValues" option set to false test': function (test) { - var filename = 'test/parser/projects/with_omit_empty_values_disabled.pbxproj' - var expectedFilename = 'test/parser/projects/expected/with_omit_empty_values_disabled_expected.pbxproj' - var content = fs.readFileSync(expectedFilename, 'utf-8').replace(/ /g, '\t'); - var project = new pbx(filename); + testProjectContents('test/parser/projects/with_array.pbxproj', 'test/parser/projects/expected/with_array_expected.pbxproj'); + }); + + it('should write out the "section" test', () => { + testProjectContents('test/parser/projects/section.pbxproj'); + }); + + it('should write out the "two-sections" test', () => { + testProjectContents('test/parser/projects/two-sections.pbxproj'); + }); + + it('should write out the "section-entries" test', () => { + testProjectContents('test/parser/projects/section-entries.pbxproj'); + }); + + it('should write out the "build-config" test', () => { + testProjectContents('test/parser/projects/build-config.pbxproj'); + }); + + it('should write out the "header-search" test', () => { + testProjectContents('test/parser/projects/header-search.pbxproj'); + }); + + it('should write out the "nested-object" test', () => { + testProjectContents('test/parser/projects/nested-object.pbxproj'); + }); + + it('should write out the "build-files" test', () => { + testProjectContents('test/parser/projects/build-files.pbxproj'); + }); + + it('should write out the "file-references" test', () => { + testProjectContents('test/parser/projects/file-references.pbxproj'); + }); + + it('should not null and undefined with the "omitEmptyValues" option set to false test', (t, done) => { + const filename = 'test/parser/projects/with_omit_empty_values_disabled.pbxproj'; + const expectedFilename = 'test/parser/projects/expected/with_omit_empty_values_disabled_expected.pbxproj'; + let content = fs.readFileSync(expectedFilename, 'utf-8').replace(/ {4}/g, '\t'); + const project = new PBXProject(filename); project.parse(function (err) { if (err) { - return test.done(err); + done(err); + return assert.fail(err); } - const group = project.addPbxGroup([], 'CustomGroup', undefined) - var written = project.writeSync(); - content = content.replace('CUSTOM_GROUP_UUID_REPLACED_BY_TEST', group.uuid) - test.equal(content, written); - test.done(); + const group = project.addPbxGroup([], 'CustomGroup', undefined); + const written = project.writeSync(); + content = content.replace('CUSTOM_GROUP_UUID_REPLACED_BY_TEST', group.uuid); + assert.equal(content, written); + done(); }); - }, - 'should drop null and undefined with the "omitEmptyValues" option set to true test': function (test) { - var filename = 'test/parser/projects/with_omit_empty_values_enabled.pbxproj' - var expectedFilename = 'test/parser/projects/expected/with_omit_empty_values_enabled_expected.pbxproj' - var content = fs.readFileSync(expectedFilename, 'utf-8').replace(/ /g, '\t'); - var project = new pbx(filename); + }); + + it('should drop null and undefined with the "omitEmptyValues" option set to true test', (t, done) => { + const filename = 'test/parser/projects/with_omit_empty_values_enabled.pbxproj'; + const expectedFilename = 'test/parser/projects/expected/with_omit_empty_values_enabled_expected.pbxproj'; + let content = fs.readFileSync(expectedFilename, 'utf-8').replace(/ {4}/g, '\t'); + const project = new PBXProject(filename); project.parse(function (err) { if (err) { - return test.done(err); + done(err); + return assert.fail(err); } - var group = project.addPbxGroup([], 'CustomGroup', undefined); - var written = project.writeSync({ omitEmptyValues: true }); - content = content.replace('CUSTOM_GROUP_UUID_REPLACED_BY_TEST', group.uuid) - test.equal(content, written); - test.done(); + const group = project.addPbxGroup([], 'CustomGroup', undefined); + const written = project.writeSync({ omitEmptyValues: true }); + content = content.replace('CUSTOM_GROUP_UUID_REPLACED_BY_TEST', group.uuid); + assert.equal(content, written); + done(); }); - } -} + }); +}); diff --git a/test/removeFramework.js b/test/removeFramework.js index 20cdbde1..90979cfe 100644 --- a/test/removeFramework.js +++ b/test/removeFramework.js @@ -1,40 +1,39 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project'), - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -function nonComments(obj) { - var keys = Object.keys(obj), - newObj = {}, i = 0; +function nonComments (obj) { + const keys = Object.keys(obj); + const newObj = {}; - for (i; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { if (!/_comment$/.test(keys[i])) { newObj[keys[i]] = obj[keys[i]]; } @@ -43,155 +42,148 @@ function nonComments(obj) { return newObj; } -function frameworkSearchPaths(proj) { - var configs = nonComments(proj.pbxXCBuildConfigurationSection()), - allPaths = [], - ids = Object.keys(configs), i, buildSettings; +function frameworkSearchPaths (proj) { + const configs = nonComments(proj.pbxXCBuildConfigurationSection()); + const allPaths = []; + const ids = Object.keys(configs); + let buildSettings; - for (i = 0; i< ids.length; i++) { + for (let i = 0; i < ids.length; i++) { buildSettings = configs[ids[i]].buildSettings; - if (buildSettings['FRAMEWORK_SEARCH_PATHS']) { - allPaths.push(buildSettings['FRAMEWORK_SEARCH_PATHS']); + if (buildSettings.FRAMEWORK_SEARCH_PATHS) { + allPaths.push(buildSettings.FRAMEWORK_SEARCH_PATHS); } } return allPaths; } -exports.removeFramework = { - 'should return a pbxFile': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'); - - test.equal(newFile.constructor, pbxFile); +describe('removeFramework', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); - var deletedFile = proj.removeFramework('libsqlite3.dylib'); + it('should return a pbxFile', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + assert.equal(newFile.constructor, PBXFile); - test.equal(deletedFile.constructor, pbxFile); + const deletedFile = proj.removeFramework('libsqlite3.dylib'); + assert.equal(deletedFile.constructor, PBXFile); + }); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'); + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + assert.ok(newFile.fileRef); - test.ok(newFile.fileRef); + const deletedFile = proj.removeFramework('libsqlite3.dylib'); + assert.ok(deletedFile.fileRef); + }); - var deletedFile = proj.removeFramework('libsqlite3.dylib'); + it('should remove 2 fields from the PBXFileReference section', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const fileRefSection = proj.pbxFileReferenceSection(); + let frsLength = Object.keys(fileRefSection).length; - test.ok(deletedFile.fileRef); + assert.equal(68, frsLength); + assert.ok(fileRefSection[newFile.fileRef]); + assert.ok(fileRefSection[newFile.fileRef + '_comment']); - test.done() - }, - 'should remove 2 fields from the PBXFileReference section': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'); - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(68, frsLength); - test.ok(fileRefSection[newFile.fileRef]); - test.ok(fileRefSection[newFile.fileRef + '_comment']); - - var deletedFile = proj.removeFramework('libsqlite3.dylib'); + const deletedFile = proj.removeFramework('libsqlite3.dylib'); frsLength = Object.keys(fileRefSection).length; - test.equal(66, frsLength); - test.ok(!fileRefSection[deletedFile.fileRef]); - test.ok(!fileRefSection[deletedFile.fileRef + '_comment']); - - test.done(); - }, - 'should remove 2 fields from the PBXBuildFile section': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; + assert.equal(66, frsLength); + assert.ok(!fileRefSection[deletedFile.fileRef]); + assert.ok(!fileRefSection[deletedFile.fileRef + '_comment']); + }); - test.equal(60, bfsLength); - test.ok(buildFileSection[newFile.uuid]); - test.ok(buildFileSection[newFile.uuid + '_comment']); + it('should remove 2 fields from the PBXBuildFile section', () => { + const newFile = proj.addFramework('libsqlite3.dylib'); + const buildFileSection = proj.pbxBuildFileSection(); + let bfsLength = Object.keys(buildFileSection).length; - var deletedFile = proj.removeFramework('libsqlite3.dylib'); + assert.equal(60, bfsLength); + assert.ok(buildFileSection[newFile.uuid]); + assert.ok(buildFileSection[newFile.uuid + '_comment']); + const deletedFile = proj.removeFramework('libsqlite3.dylib'); bfsLength = Object.keys(buildFileSection).length; - test.equal(58, bfsLength); - test.ok(!buildFileSection[deletedFile.uuid]); - test.ok(!buildFileSection[deletedFile.uuid + '_comment']); + assert.equal(58, bfsLength); + assert.ok(!buildFileSection[deletedFile.uuid]); + assert.ok(!buildFileSection[deletedFile.uuid + '_comment']); + }); - test.done(); - }, - 'should remove from the Frameworks PBXGroup': function (test) { - var newLength = proj.pbxGroupByName('Frameworks').children.length + 1, - newFile = proj.addFramework('libsqlite3.dylib'), - frameworks = proj.pbxGroupByName('Frameworks'); + it('should remove from the Frameworks PBXGroup', () => { + let newLength = proj.pbxGroupByName('Frameworks').children.length + 1; + proj.addFramework('libsqlite3.dylib'); - test.equal(frameworks.children.length, newLength); + const frameworks = proj.pbxGroupByName('Frameworks'); + assert.equal(frameworks.children.length, newLength); - var deletedFile = proj.removeFramework('libsqlite3.dylib'), + proj.removeFramework('libsqlite3.dylib'); newLength = newLength - 1; - test.equal(frameworks.children.length, newLength); + assert.equal(frameworks.children.length, newLength); + }); - test.done(); - }, - 'should remove from the PBXFrameworksBuildPhase': function (test) { - var newFile = proj.addFramework('libsqlite3.dylib'), - frameworks = proj.pbxFrameworksBuildPhaseObj(); + it('should remove from the PBXFrameworksBuildPhase', () => { + proj.addFramework('libsqlite3.dylib'); - test.equal(frameworks.files.length, 16); + let frameworks = proj.pbxFrameworksBuildPhaseObj(); + assert.equal(frameworks.files.length, 16); - var deletedFile = proj.removeFramework('libsqlite3.dylib'), - frameworks = proj.pbxFrameworksBuildPhaseObj(); + proj.removeFramework('libsqlite3.dylib'); - test.equal(frameworks.files.length, 15); + frameworks = proj.pbxFrameworksBuildPhaseObj(); + assert.equal(frameworks.files.length, 15); + }); - test.done(); - }, - 'should remove custom frameworks': function (test) { - var newFile = proj.addFramework('/path/to/Custom.framework', { customFramework: true }), - frameworks = proj.pbxFrameworksBuildPhaseObj(); + it('should remove custom frameworks', () => { + proj.addFramework('/path/to/Custom.framework', { customFramework: true }); - test.equal(frameworks.files.length, 16); + let frameworks = proj.pbxFrameworksBuildPhaseObj(); + assert.equal(frameworks.files.length, 16); - var deletedFile = proj.removeFramework('/path/to/Custom.framework', { customFramework: true }), - frameworks = proj.pbxFrameworksBuildPhaseObj(); + proj.removeFramework('/path/to/Custom.framework', { customFramework: true }); - test.equal(frameworks.files.length, 15); + frameworks = proj.pbxFrameworksBuildPhaseObj(); + assert.equal(frameworks.files.length, 15); - var frameworkPaths = frameworkSearchPaths(proj); - expectedPath = '"/path/to"'; + const frameworkPaths = frameworkSearchPaths(proj); + const expectedPath = '"/path/to"'; - for (i = 0; i < frameworkPaths.length; i++) { - var current = frameworkPaths[i]; - test.ok(current.indexOf(expectedPath) == -1); + for (let i = 0; i < frameworkPaths.length; i++) { + const current = frameworkPaths[i]; + assert.ok(current.indexOf(expectedPath) === -1); } + }); - test.done(); - }, - 'should remove embedded frameworks': function (test) { - var newFile = proj.addFramework('/path/to/Custom.framework', { customFramework: true, embed:true, sign:true }), - frameworks = proj.pbxFrameworksBuildPhaseObj(), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; + it('should remove embedded frameworks', () => { + proj.addFramework('/path/to/Custom.framework', { customFramework: true, embed: true, sign: true }); - test.equal(frameworks.files.length, 16); - test.equal(62, bfsLength); + let frameworks = proj.pbxFrameworksBuildPhaseObj(); + let buildFileSection = proj.pbxBuildFileSection(); + let bfsLength = Object.keys(buildFileSection).length; - var deletedFile = proj.removeFramework('/path/to/Custom.framework', { customFramework: true, embed:true }), - frameworks = proj.pbxFrameworksBuildPhaseObj(), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; + assert.equal(frameworks.files.length, 16); + assert.equal(62, bfsLength); - test.equal(frameworks.files.length, 15); - test.equal(58, bfsLength); + proj.removeFramework('/path/to/Custom.framework', { customFramework: true, embed: true }); - var frameworkPaths = frameworkSearchPaths(proj); - expectedPath = '"/path/to"'; + frameworks = proj.pbxFrameworksBuildPhaseObj(); + buildFileSection = proj.pbxBuildFileSection(); + bfsLength = Object.keys(buildFileSection).length; - for (i = 0; i < frameworkPaths.length; i++) { - var current = frameworkPaths[i]; - test.ok(current.indexOf(expectedPath) == -1); - } + assert.equal(frameworks.files.length, 15); + assert.equal(58, bfsLength); - test.done(); - } -} + const frameworkPaths = frameworkSearchPaths(proj); + const expectedPath = '"/path/to"'; + + for (let i = 0; i < frameworkPaths.length; i++) { + const current = frameworkPaths[i]; + assert.ok(current.indexOf(expectedPath) === -1); + } + }); +}); diff --git a/test/removeHeaderFile.js b/test/removeHeaderFile.js index acda1613..989e5af3 100644 --- a/test/removeHeaderFile.js +++ b/test/removeHeaderFile.js @@ -1,122 +1,114 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} - -exports.removeHeaderFile = { - 'should return a pbxFile': function (test) { - var newFile = proj.addHeaderFile('file.h'); - - test.equal(newFile.constructor, pbxFile); - - var deletedFile = proj.removeHeaderFile('file.h'); - - test.equal(deletedFile.constructor, pbxFile); - - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addHeaderFile('file.h'); - - test.ok(newFile.fileRef); - - var deletedFile = proj.removeHeaderFile('file.h'); - - test.ok(deletedFile.fileRef); - - test.done() - }, - 'should remove 2 fields from the PBXFileReference section': function (test) { - var newFile = proj.addHeaderFile('file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(68, frsLength); - test.ok(fileRefSection[newFile.fileRef]); - test.ok(fileRefSection[newFile.fileRef + '_comment']); - - var deletedFile = proj.removeHeaderFile('file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; - - test.equal(66, frsLength); - test.ok(!fileRefSection[deletedFile.fileRef]); - test.ok(!fileRefSection[deletedFile.fileRef + '_comment']); - - test.done(); - }, - 'should remove comment from the PBXFileReference correctly': function (test) { - var newFile = proj.addHeaderFile('file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = newFile.fileRef + '_comment'; - - test.equal(fileRefSection[commentKey], 'file.h'); - - var deletedFile = proj.removeHeaderFile('file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = deletedFile.fileRef + '_comment'; - test.ok(!fileRefSection[commentKey]); - - test.done(); - }, - 'should remove the PBXFileReference object correctly': function (test) { - var newFile = proj.addHeaderFile('Plugins/file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; - - test.equal(fileRefEntry.isa, 'PBXFileReference'); - test.equal(fileRefEntry.fileEncoding, 4); - test.equal(fileRefEntry.lastKnownFileType, 'sourcecode.c.h'); - test.equal(fileRefEntry.name, '"file.h"'); - test.equal(fileRefEntry.path, '"file.h"'); - test.equal(fileRefEntry.sourceTree, '""'); - - var deletedFile = proj.removeHeaderFile('Plugins/file.h'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[deletedFile.fileRef]; - - test.ok(!fileRefEntry); - - test.done(); - }, - 'should remove from the Plugins PBXGroup group': function (test) { - var newFile = proj.addHeaderFile('Plugins/file.h'), - plugins = proj.pbxGroupByName('Plugins'); - - test.equal(plugins.children.length, 1); - - var deletedFile = proj.removeHeaderFile('Plugins/file.h'), - plugins = proj.pbxGroupByName('Plugins'); - - test.equal(plugins.children.length, 0); - - test.done(); - } -} +describe('removeHeaderFile', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxFile', () => { + const newFile = proj.addHeaderFile('file.h'); + assert.equal(newFile.constructor, PBXFile); + + const deletedFile = proj.removeHeaderFile('file.h'); + assert.equal(deletedFile.constructor, PBXFile); + }); + + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addHeaderFile('file.h'); + assert.ok(newFile.fileRef); + + const deletedFile = proj.removeHeaderFile('file.h'); + assert.ok(deletedFile.fileRef); + }); + + it('should remove 2 fields from the PBXFileReference section', () => { + const newFile = proj.addHeaderFile('file.h'); + let fileRefSection = proj.pbxFileReferenceSection(); + let frsLength = Object.keys(fileRefSection).length; + + assert.equal(68, frsLength); + assert.ok(fileRefSection[newFile.fileRef]); + assert.ok(fileRefSection[newFile.fileRef + '_comment']); + + const deletedFile = proj.removeHeaderFile('file.h'); + fileRefSection = proj.pbxFileReferenceSection(); + frsLength = Object.keys(fileRefSection).length; + + assert.equal(66, frsLength); + assert.ok(!fileRefSection[deletedFile.fileRef]); + assert.ok(!fileRefSection[deletedFile.fileRef + '_comment']); + }); + + it('should remove comment from the PBXFileReference correctly', () => { + const newFile = proj.addHeaderFile('file.h'); + let fileRefSection = proj.pbxFileReferenceSection(); + let commentKey = newFile.fileRef + '_comment'; + + assert.equal(fileRefSection[commentKey], 'file.h'); + + const deletedFile = proj.removeHeaderFile('file.h'); + fileRefSection = proj.pbxFileReferenceSection(); + commentKey = deletedFile.fileRef + '_comment'; + assert.ok(!fileRefSection[commentKey]); + }); + + it('should remove the PBXFileReference object correctly', () => { + const newFile = proj.addHeaderFile('Plugins/file.h'); + let fileRefSection = proj.pbxFileReferenceSection(); + let fileRefEntry = fileRefSection[newFile.fileRef]; + + assert.equal(fileRefEntry.isa, 'PBXFileReference'); + assert.equal(fileRefEntry.fileEncoding, 4); + assert.equal(fileRefEntry.lastKnownFileType, 'sourcecode.c.h'); + assert.equal(fileRefEntry.name, '"file.h"'); + assert.equal(fileRefEntry.path, '"file.h"'); + assert.equal(fileRefEntry.sourceTree, '""'); + + const deletedFile = proj.removeHeaderFile('Plugins/file.h'); + fileRefSection = proj.pbxFileReferenceSection(); + fileRefEntry = fileRefSection[deletedFile.fileRef]; + + assert.ok(!fileRefEntry); + }); + + it('should remove from the Plugins PBXGroup group', () => { + proj.addHeaderFile('Plugins/file.h'); + let plugins = proj.pbxGroupByName('Plugins'); + + assert.equal(plugins.children.length, 1); + + proj.removeHeaderFile('Plugins/file.h'); + plugins = proj.pbxGroupByName('Plugins'); + + assert.equal(plugins.children.length, 0); + }); +}); diff --git a/test/removeResourceFile.js b/test/removeResourceFile.js index bda48f92..e5e4cb9c 100644 --- a/test/removeResourceFile.js +++ b/test/removeResourceFile.js @@ -1,201 +1,195 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach, afterEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('removeResourceFile', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); + + it('should return a pbxFile', () => { + const newFile = proj.addResourceFile('assets.bundle'); -exports.removeResourceFile = { - 'should return a pbxFile': function (test) { - var newFile = proj.addResourceFile('assets.bundle'); + assert.equal(newFile.constructor, PBXFile); - test.equal(newFile.constructor, pbxFile); + const deletedFile = proj.removeResourceFile('assets.bundle'); - var deletedFile = proj.removeResourceFile('assets.bundle'); + assert.equal(deletedFile.constructor, PBXFile); + }); - test.equal(deletedFile.constructor, pbxFile); + it('should set a uuid on the pbxFile', () => { + const newFile = proj.addResourceFile('assets.bundle'); - test.done() - }, - 'should set a uuid on the pbxFile': function (test) { - var newFile = proj.addResourceFile('assets.bundle'); + assert.ok(newFile.uuid); - test.ok(newFile.uuid); + const deletedFile = proj.removeResourceFile('assets.bundle'); - var deletedFile = proj.removeResourceFile('assets.bundle'); + assert.ok(deletedFile.uuid); + }); - test.ok(deletedFile.uuid); + it('should set a fileRef on the pbxFile', () => { + const newFile = proj.addResourceFile('assets.bundle'); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { - var newFile = proj.addResourceFile('assets.bundle'); + assert.ok(newFile.fileRef); - test.ok(newFile.fileRef); + const deletedFile = proj.removeResourceFile('assets.bundle'); - var deletedFile = proj.removeResourceFile('assets.bundle'); + assert.ok(deletedFile.fileRef); + }); - test.ok(deletedFile.fileRef); + it('should remove 2 fields from the PBXBuildFile section', () => { + const newFile = proj.addResourceFile('assets.bundle'); + let buildFileSection = proj.pbxBuildFileSection(); + let bfsLength = Object.keys(buildFileSection).length; - test.done() - }, - 'should remove 2 fields from the PBXBuildFile section': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; + assert.equal(60, bfsLength); + assert.ok(buildFileSection[newFile.uuid]); + assert.ok(buildFileSection[newFile.uuid + '_comment']); - test.equal(60, bfsLength); - test.ok(buildFileSection[newFile.uuid]); - test.ok(buildFileSection[newFile.uuid + '_comment']); + const deletedFile = proj.removeResourceFile('assets.bundle'); + buildFileSection = proj.pbxBuildFileSection(); + bfsLength = Object.keys(buildFileSection).length; - var deletedFile = proj.removeResourceFile('assets.bundle'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; + assert.equal(58, bfsLength); + assert.ok(!buildFileSection[deletedFile.uuid]); + assert.ok(!buildFileSection[deletedFile.uuid + '_comment']); + }); - test.equal(58, bfsLength); - test.ok(!buildFileSection[deletedFile.uuid]); - test.ok(!buildFileSection[deletedFile.uuid + '_comment']); + it('should remove the PBXBuildFile comment correctly', () => { + const newFile = proj.addResourceFile('assets.bundle'); + let commentKey = newFile.uuid + '_comment'; + let buildFileSection = proj.pbxBuildFileSection(); - test.done(); - }, - 'should remove the PBXBuildFile comment correctly': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - commentKey = newFile.uuid + '_comment', - buildFileSection = proj.pbxBuildFileSection(); + assert.equal(buildFileSection[commentKey], 'assets.bundle in Resources'); - test.equal(buildFileSection[commentKey], 'assets.bundle in Resources'); + const deletedFile = proj.removeResourceFile('assets.bundle'); + commentKey = deletedFile.uuid + '_comment'; + buildFileSection = proj.pbxBuildFileSection(); - var deletedFile = proj.removeResourceFile('assets.bundle'), - commentKey = deletedFile.uuid + '_comment', - buildFileSection = proj.pbxBuildFileSection(); + assert.ok(!buildFileSection[commentKey]); + }); - test.ok(!buildFileSection[commentKey]); + it('should remove the PBXBuildFile object correctly', () => { + const newFile = proj.addResourceFile('assets.bundle'); + let buildFileSection = proj.pbxBuildFileSection(); + let buildFileEntry = buildFileSection[newFile.uuid]; - test.done(); - }, - 'should remove the PBXBuildFile object correctly': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[newFile.uuid]; + assert.equal(buildFileEntry.isa, 'PBXBuildFile'); + assert.equal(buildFileEntry.fileRef, newFile.fileRef); + assert.equal(buildFileEntry.fileRef_comment, 'assets.bundle'); - test.equal(buildFileEntry.isa, 'PBXBuildFile'); - test.equal(buildFileEntry.fileRef, newFile.fileRef); - test.equal(buildFileEntry.fileRef_comment, 'assets.bundle'); + const deletedFile = proj.removeResourceFile('assets.bundle'); + buildFileSection = proj.pbxBuildFileSection(); + buildFileEntry = buildFileSection[deletedFile.uuid]; - var deletedFile = proj.removeResourceFile('assets.bundle'), - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[deletedFile.uuid]; + assert.ok(!buildFileEntry); + }); - test.ok(!buildFileEntry); + it('should remove 2 fields from the PBXFileReference section', () => { + const newFile = proj.addResourceFile('assets.bundle'); + let fileRefSection = proj.pbxFileReferenceSection(); + let frsLength = Object.keys(fileRefSection).length; - test.done(); - }, - 'should remove 2 fields from the PBXFileReference section': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; + assert.equal(68, frsLength); + assert.ok(fileRefSection[newFile.fileRef]); + assert.ok(fileRefSection[newFile.fileRef + '_comment']); - test.equal(68, frsLength); - test.ok(fileRefSection[newFile.fileRef]); - test.ok(fileRefSection[newFile.fileRef + '_comment']); + const deletedFile = proj.removeResourceFile('assets.bundle'); + fileRefSection = proj.pbxFileReferenceSection(); + frsLength = Object.keys(fileRefSection).length; - var deletedFile = proj.removeResourceFile('assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; + assert.equal(66, frsLength); + assert.ok(!fileRefSection[deletedFile.fileRef]); + assert.ok(!fileRefSection[deletedFile.fileRef + '_comment']); + }); - test.equal(66, frsLength); - test.ok(!fileRefSection[deletedFile.fileRef]); - test.ok(!fileRefSection[deletedFile.fileRef + '_comment']); + it('should populate the PBXFileReference comment correctly', () => { + const newFile = proj.addResourceFile('assets.bundle'); + let fileRefSection = proj.pbxFileReferenceSection(); + let commentKey = newFile.fileRef + '_comment'; - test.done(); - }, - 'should populate the PBXFileReference comment correctly': function (test) { - var newFile = proj.addResourceFile('assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = newFile.fileRef + '_comment'; + assert.equal(fileRefSection[commentKey], 'assets.bundle'); - test.equal(fileRefSection[commentKey], 'assets.bundle'); + const deletedFile = proj.removeResourceFile('assets.bundle'); + fileRefSection = proj.pbxFileReferenceSection(); + commentKey = deletedFile.fileRef + '_comment'; - var deletedFile = proj.removeResourceFile('assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = deletedFile.fileRef + '_comment'; + assert.ok(!fileRefSection[commentKey]); + }); - test.ok(!fileRefSection[commentKey]); - test.done(); - }, - 'should remove the PBXFileReference object correctly': function (test) { + it('should remove the PBXFileReference object correctly', () => { delete proj.pbxGroupByName('Resources').path; - var newFile = proj.addResourceFile('Resources/assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; + const newFile = proj.addResourceFile('Resources/assets.bundle'); + let fileRefSection = proj.pbxFileReferenceSection(); + let fileRefEntry = fileRefSection[newFile.fileRef]; + + assert.equal(fileRefEntry.isa, 'PBXFileReference'); + assert.equal(fileRefEntry.fileEncoding, undefined); + assert.equal(fileRefEntry.lastKnownFileType, 'wrapper.plug-in'); + assert.equal(fileRefEntry.name, '"assets.bundle"'); + assert.equal(fileRefEntry.path, '"Resources/assets.bundle"'); + assert.equal(fileRefEntry.sourceTree, '""'); - test.equal(fileRefEntry.isa, 'PBXFileReference'); - test.equal(fileRefEntry.fileEncoding, undefined); - test.equal(fileRefEntry.lastKnownFileType, 'wrapper.plug-in'); - test.equal(fileRefEntry.name, '"assets.bundle"'); - test.equal(fileRefEntry.path, '"Resources/assets.bundle"'); - test.equal(fileRefEntry.sourceTree, '""'); + const deletedFile = proj.removeResourceFile('Resources/assets.bundle'); + fileRefSection = proj.pbxFileReferenceSection(); + fileRefEntry = fileRefSection[deletedFile.fileRef]; - var deletedFile = proj.removeResourceFile('Resources/assets.bundle'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[deletedFile.fileRef]; + assert.ok(!fileRefEntry); + }); - test.ok(!fileRefEntry); + it('should remove from the Resources PBXGroup group', () => { + proj.addResourceFile('Resources/assets.bundle'); + let resources = proj.pbxGroupByName('Resources'); - test.done(); - }, - 'should remove from the Resources PBXGroup group': function (test) { - var newFile = proj.addResourceFile('Resources/assets.bundle'), - resources = proj.pbxGroupByName('Resources'); + assert.equal(resources.children.length, 10); - test.equal(resources.children.length, 10); + proj.removeResourceFile('Resources/assets.bundle'); + resources = proj.pbxGroupByName('Resources'); - var deletedFile = proj.removeResourceFile('Resources/assets.bundle'), - resources = proj.pbxGroupByName('Resources'); + assert.equal(resources.children.length, 9); + }); - test.equal(resources.children.length, 9); - test.done(); - }, - 'should remove from the PBXSourcesBuildPhase': function (test) { - var newFile = proj.addResourceFile('Resources/assets.bundle'), - sources = proj.pbxResourcesBuildPhaseObj(); + it('should remove from the PBXSourcesBuildPhase', () => { + proj.addResourceFile('Resources/assets.bundle'); + let sources = proj.pbxResourcesBuildPhaseObj(); - test.equal(sources.files.length, 13); + assert.equal(sources.files.length, 13); - var deletedFile = proj.removeResourceFile('Resources/assets.bundle'), - sources = proj.pbxResourcesBuildPhaseObj(); + proj.removeResourceFile('Resources/assets.bundle'); + sources = proj.pbxResourcesBuildPhaseObj(); - test.equal(sources.files.length, 12); - test.done(); - }, - tearDown: function (callback) { + assert.equal(sources.files.length, 12); + }); + + afterEach(() => { delete proj.pbxGroupByName('Resources').path; - callback(); - } -} + }); +}); diff --git a/test/removeSourceFile.js b/test/removeSourceFile.js index de7895e5..c4d78d41 100644 --- a/test/removeSourceFile.js +++ b/test/removeSourceFile.js @@ -1,163 +1,161 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var fullProject = require('./fixtures/full-project') - fullProjectStr = JSON.stringify(fullProject), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'); - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const fullProject = require('./fixtures/full-project'); +const fullProjectStr = JSON.stringify(fullProject); +const PBXProject = require('../lib/pbxProject'); +const PBXFile = require('../lib/pbxFile'); +const proj = new PBXProject('.'); + +function cleanHash () { return JSON.parse(fullProjectStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +describe('removeSourceFile', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.removeSourceFile = { - 'should return a pbxFile': function (test) { + it('should return a pbxFile', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('file.m'); + const newFile = proj.removeSourceFile('file.m'); + + assert.equal(newFile.constructor, PBXFile); + }); - test.equal(newFile.constructor, pbxFile); - test.done() - }, - 'should set a uuid on the pbxFile': function (test) { + it('should set a uuid on the pbxFile', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('file.m'); + const newFile = proj.removeSourceFile('file.m'); - test.ok(newFile.uuid); - test.done() - }, - 'should set a fileRef on the pbxFile': function (test) { + assert.ok(newFile.uuid); + }); + + it('should set a fileRef on the pbxFile', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('file.m'); + const newFile = proj.removeSourceFile('file.m'); + + assert.ok(newFile.fileRef); + }); - test.ok(newFile.fileRef); - test.done() - }, - 'should remove 2 fields from the PBXBuildFile section': function (test) { + it('should remove 2 fields from the PBXBuildFile section', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('file.m'), - buildFileSection = proj.pbxBuildFileSection(), - bfsLength = Object.keys(buildFileSection).length; + const newFile = proj.removeSourceFile('file.m'); + const buildFileSection = proj.pbxBuildFileSection(); + const bfsLength = Object.keys(buildFileSection).length; - test.equal(58, bfsLength); - test.ok(!buildFileSection[newFile.uuid]); - test.ok(!buildFileSection[newFile.uuid + '_comment']); + assert.equal(58, bfsLength); + assert.ok(!buildFileSection[newFile.uuid]); + assert.ok(!buildFileSection[newFile.uuid + '_comment']); + }); - test.done(); - }, - 'should remove comment from the PBXBuildFile correctly': function (test) { + it('should remove comment from the PBXBuildFile correctly', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('file.m'), - commentKey = newFile.uuid + '_comment', - buildFileSection = proj.pbxBuildFileSection(); - test.notEqual(!buildFileSection[commentKey], 'file.m in Sources'); - test.done(); - }, - 'should remove the PBXBuildFile object correctly': function (test) { + const newFile = proj.removeSourceFile('file.m'); + const commentKey = newFile.uuid + '_comment'; + const buildFileSection = proj.pbxBuildFileSection(); + assert.notEqual(!buildFileSection[commentKey], 'file.m in Sources'); + }); + + it('should remove the PBXBuildFile object correctly', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('file.m'), - buildFileSection = proj.pbxBuildFileSection(), - buildFileEntry = buildFileSection[newFile.uuid]; + const newFile = proj.removeSourceFile('file.m'); + const buildFileSection = proj.pbxBuildFileSection(); + const buildFileEntry = buildFileSection[newFile.uuid]; - test.equal(buildFileEntry, undefined); + assert.equal(buildFileEntry, undefined); + }); - test.done(); - }, - 'should remove 2 fields from the PBXFileReference section': function (test) { + it('should remove 2 fields from the PBXFileReference section', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('file.m'), - fileRefSection = proj.pbxFileReferenceSection(), - frsLength = Object.keys(fileRefSection).length; + const newFile = proj.removeSourceFile('file.m'); + const fileRefSection = proj.pbxFileReferenceSection(); + const frsLength = Object.keys(fileRefSection).length; - test.equal(66, frsLength); - test.ok(!fileRefSection[newFile.fileRef]); - test.ok(!fileRefSection[newFile.fileRef + '_comment']); + assert.equal(66, frsLength); + assert.ok(!fileRefSection[newFile.fileRef]); + assert.ok(!fileRefSection[newFile.fileRef + '_comment']); + }); - test.done(); - }, - 'should remove the PBXFileReference comment correctly': function (test) { + it('should remove the PBXFileReference comment correctly', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('file.m'), - fileRefSection = proj.pbxFileReferenceSection(), - commentKey = newFile.fileRef + '_comment'; - - test.ok(!fileRefSection[commentKey]); - test.done(); - }, - 'should remove the PBXFileReference object correctly': function (test) { + const newFile = proj.removeSourceFile('file.m'); + const fileRefSection = proj.pbxFileReferenceSection(); + const commentKey = newFile.fileRef + '_comment'; + + assert.ok(!fileRefSection[commentKey]); + }); + + it('should remove the PBXFileReference object correctly', () => { proj.addSourceFile('file.m'); - var newFile = proj.removeSourceFile('Plugins/file.m'), - fileRefSection = proj.pbxFileReferenceSection(), - fileRefEntry = fileRefSection[newFile.fileRef]; - test.ok(!fileRefEntry); - test.done(); - }, - 'should remove from the Plugins PBXGroup group': function (test) { + const newFile = proj.removeSourceFile('Plugins/file.m'); + const fileRefSection = proj.pbxFileReferenceSection(); + const fileRefEntry = fileRefSection[newFile.fileRef]; + assert.ok(!fileRefEntry); + }); + + it('should remove from the Plugins PBXGroup group', () => { proj.addSourceFile('Plugins/file.m'); - var newFile = proj.removeSourceFile('Plugins/file.m'), - plugins = proj.pbxGroupByName('Plugins'); - test.equal(plugins.children.length, 0); - test.done(); - }, - 'should have the right values for the PBXGroup entry': function (test) { + proj.removeSourceFile('Plugins/file.m'); + const plugins = proj.pbxGroupByName('Plugins'); + assert.equal(plugins.children.length, 0); + }); + + it('should have the right values for the PBXGroup entry', () => { proj.addSourceFile('Plugins/file.m'); - var newFile = proj.removeSourceFile('Plugins/file.m'), - plugins = proj.pbxGroupByName('Plugins'), - pluginObj = plugins.children[0]; - - test.ok(!pluginObj); - test.done(); - }, - 'should remove from the PBXSourcesBuildPhase': function (test) { + proj.removeSourceFile('Plugins/file.m'); + const plugins = proj.pbxGroupByName('Plugins'); + const pluginObj = plugins.children[0]; + + assert.ok(!pluginObj); + }); + + it('should remove from the PBXSourcesBuildPhase', () => { proj.addSourceFile('Plugins/file.m'); - var newFile = proj.removeSourceFile('Plugins/file.m'), - sources = proj.pbxSourcesBuildPhaseObj(); + proj.removeSourceFile('Plugins/file.m'); + const sources = proj.pbxSourcesBuildPhaseObj(); + + assert.equal(sources.files.length, 2); + }); - test.equal(sources.files.length, 2); - test.done(); - }, - 'should have the right values for the Sources entry': function (test) { + it('should have the right values for the Sources entry', () => { proj.addSourceFile('Plugins/file.m'); - var newFile = proj.removeSourceFile('Plugins/file.m'), - sources = proj.pbxSourcesBuildPhaseObj(), - sourceObj = sources.files[2]; + proj.removeSourceFile('Plugins/file.m'); + const sources = proj.pbxSourcesBuildPhaseObj(); + const sourceObj = sources.files[2]; - test.ok(!sourceObj); - test.done(); - }, - 'should remove file from PBXFileReference after modified by Xcode': function(test) { - var fileRef = proj.addSourceFile('Plugins/file.m').fileRef; + assert.ok(!sourceObj); + }); + + it('should remove file from PBXFileReference after modified by Xcode', () => { + const fileRef = proj.addSourceFile('Plugins/file.m').fileRef; // Simulate Xcode's behaviour of stripping quotes around path and name // properties. - var entry = proj.pbxFileReferenceSection()[fileRef]; - entry.name = entry.name.replace(/^"(.*)"$/, "$1"); - entry.path = entry.path.replace(/^"(.*)"$/, "$1"); - - var newFile = proj.removeSourceFile('Plugins/file.m'); + const entry = proj.pbxFileReferenceSection()[fileRef]; + entry.name = entry.name.replace(/^"(.*)"$/, '$1'); + entry.path = entry.path.replace(/^"(.*)"$/, '$1'); - test.ok(newFile.uuid); - test.ok(!proj.pbxFileReferenceSection()[fileRef]); - test.done(); - } -} + const newFile = proj.removeSourceFile('Plugins/file.m'); + assert.ok(newFile.uuid); + assert.ok(!proj.pbxFileReferenceSection()[fileRef]); + }); +}); diff --git a/test/variantGroup.js b/test/variantGroup.js index 356a2320..6718acac 100644 --- a/test/variantGroup.js +++ b/test/variantGroup.js @@ -1,28 +1,32 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var pbx = require('../lib/pbxProject'), - project, - projectHash; - -var findChildInGroup = function(obj, target) { - var found = false; - - for (var i = 0, j = obj.children.length; i < j; i++) { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const PBXProject = require('../lib/pbxProject'); +let project; + +const findChildInGroup = function (obj, target) { + let found = false; + + for (let i = 0, j = obj.children.length; i < j; i++) { if (obj.children[i].value === target) { found = true; break; @@ -30,165 +34,128 @@ var findChildInGroup = function(obj, target) { } return found; -} +}; -var findFileByUUID = function(obj, target) { - var found = false; - - for (var k = 0, l = obj.files.length; k < l; k++) { - if (obj.files[k].value === target) { - found = true; - break; - } - } - - return found; -} - -var findByFileRef = function(obj, target) { - var found = false; - - for (var property in obj) { +const findByName = function (obj, target) { + let found = false; + for (const property in obj) { if (!/comment/.test(property)) { - if (obj[property].fileRef === target) { - found = true; - break; - } - } - } - return found; -} - -var findByName = function(obj, target) { - var found = false; - for (var property in obj) { - if (!/comment/.test(property)) { - var value = obj[property]; + const value = obj[property]; if (value.name === target) { found = true; } } } return found; -} - -exports.setUp = function(callback) { - project = new pbx('test/parser/projects/variantgroup.pbxproj'); - projectHash = project.parseSync(); - callback(); -} - -exports.getVariantGroupByKey = { - 'should return PBXVariantGroup for Localizable.strings': function(test) { - var groupKey = project.findPBXVariantGroupKey({name: 'Localizable.strings'}); - var group = project.getPBXVariantGroupByKey(groupKey); - test.ok(group.name === 'Localizable.strings'); - test.done(); - } -} - -exports.createVariantGroup = { - 'should create a new Test Variant Group': function(test) { - delete project.getPBXObject('PBXVariantGroup'); - - var found = false; - var groups = project.getPBXObject('PBXVariantGroup'); - - var found = findByName(groups, 'Test'); - test.ok(found === false); - - var group = project.findPBXVariantGroupKey({name:'Test'}); - test.ok(group === undefined); - - project.pbxCreateVariantGroup('Test'); - - groups = project.getPBXObject('PBXVariantGroup'); - found = findByName(groups, 'Test'); - test.ok(found === true); - - group = project.findPBXVariantGroupKey({name:'Test'}); - test.ok(typeof group === 'string'); - test.done(); - } -} - -exports.findVariantGroupKey = { - 'should return a valid group key':function(test) { - var keyByName = project.findPBXVariantGroupKey({ name: 'Localizable.strings'}); - var nonExistingKey = project.findPBXVariantGroupKey({ name: 'Foo'}); - - test.ok(keyByName === '07E3BDBC1DF1DEA500E49912'); - test.ok(nonExistingKey === undefined); - - test.done(); - } -} - -exports.createLocalisationVariantGroup = { - 'should create a new localisation variationgroup then add group to Resources group': function(test) { - delete project.getPBXObject('PBXVariantGroup'); - - var localizationVariantGp = project.addLocalizationVariantGroup('InfoPlist.strings'); - - var resourceGroupKey = project.findPBXGroupKey({name: 'Resources'}); - var resourceGroup = project.getPBXGroupByKey(resourceGroupKey); - var foundInResourcesGroup = findChildInGroup(resourceGroup, localizationVariantGp.fileRef ); - test.ok(foundInResourcesGroup); - - var foundInResourcesBuildPhase = false; - var sources = project.pbxResourcesBuildPhaseObj(); - for (var i = 0, j = sources.files.length; i < j; i++) { - var file = sources.files[i]; - if (file.value === localizationVariantGp.uuid) { - foundInResourcesBuildPhase = true; +}; + +describe('variantGroup', () => { + beforeEach(() => { + project = new PBXProject('test/parser/projects/variantgroup.pbxproj'); + project.parseSync(); + }); + + describe('getVariantGroupByKey', () => { + it('should return PBXVariantGroup for Localizable.strings', () => { + const groupKey = project.findPBXVariantGroupKey({ name: 'Localizable.strings' }); + const group = project.getPBXVariantGroupByKey(groupKey); + assert.ok(group.name === 'Localizable.strings'); + }); + }); + + describe('createVariantGroup', () => { + it('should create a new Test Variant Group', () => { + delete project.getPBXObject('PBXVariantGroup'); + + let found = false; + let groups = project.getPBXObject('PBXVariantGroup'); + + found = findByName(groups, 'Test'); + assert.ok(found === false); + + let group = project.findPBXVariantGroupKey({ name: 'Test' }); + assert.ok(group === undefined); + + project.pbxCreateVariantGroup('Test'); + + groups = project.getPBXObject('PBXVariantGroup'); + found = findByName(groups, 'Test'); + assert.ok(found === true); + + group = project.findPBXVariantGroupKey({ name: 'Test' }); + assert.ok(typeof group === 'string'); + }); + }); + + describe('findVariantGroupKey', () => { + it('should return a valid group key', () => { + const keyByName = project.findPBXVariantGroupKey({ name: 'Localizable.strings' }); + const nonExistingKey = project.findPBXVariantGroupKey({ name: 'Foo' }); + + assert.ok(keyByName === '07E3BDBC1DF1DEA500E49912'); + assert.ok(nonExistingKey === undefined); + }); + }); + + describe('createLocalisationVariantGroup', () => { + it('should create a new localisation variationgroup then add group to Resources group', () => { + delete project.getPBXObject('PBXVariantGroup'); + + const localizationVariantGp = project.addLocalizationVariantGroup('InfoPlist.strings'); + + const resourceGroupKey = project.findPBXGroupKey({ name: 'Resources' }); + const resourceGroup = project.getPBXGroupByKey(resourceGroupKey); + const foundInResourcesGroup = findChildInGroup(resourceGroup, localizationVariantGp.fileRef); + assert.ok(foundInResourcesGroup); + + let foundInResourcesBuildPhase = false; + const sources = project.pbxResourcesBuildPhaseObj(); + for (let i = 0, j = sources.files.length; i < j; i++) { + const file = sources.files[i]; + if (file.value === localizationVariantGp.uuid) { + foundInResourcesBuildPhase = true; + } } - } - test.ok(foundInResourcesBuildPhase); - - test.done(); - } -} - -exports.addResourceFileToLocalisationGroup = { - 'should add resource file to the TestVariantGroup group' : function(test) { - - var infoPlistVarGp = project.addLocalizationVariantGroup('InfoPlist.strings'); - var testKey = infoPlistVarGp.fileRef; - var file = project.addResourceFile('Resources/en.lproj/Localization.strings', {variantGroup: true}, testKey); - - var foundInLocalisationVariantGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey), file.fileRef ); - test.ok(foundInLocalisationVariantGroup); - - var foundInResourcesBuildPhase = false; - var sources = project.pbxResourcesBuildPhaseObj(); - for (var i = 0, j = sources.files.length; i < j; i++) { - var sourceFile = sources.files[i]; - if (sourceFile.value === file.fileRef) { - foundInResourcesBuildPhase = true; + assert.ok(foundInResourcesBuildPhase); + }); + }); + + describe('addResourceFileToLocalisationGroup', () => { + it('should add resource file to the TestVariantGroup group', () => { + const infoPlistVarGp = project.addLocalizationVariantGroup('InfoPlist.strings'); + const testKey = infoPlistVarGp.fileRef; + const file = project.addResourceFile('Resources/en.lproj/Localization.strings', { variantGroup: true }, testKey); + + const foundInLocalisationVariantGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey), file.fileRef); + assert.ok(foundInLocalisationVariantGroup); + + let foundInResourcesBuildPhase = false; + const sources = project.pbxResourcesBuildPhaseObj(); + for (let i = 0, j = sources.files.length; i < j; i++) { + const sourceFile = sources.files[i]; + if (sourceFile.value === file.fileRef) { + foundInResourcesBuildPhase = true; + } } - } - test.ok(!foundInResourcesBuildPhase); - - var buildFileSection = project.pbxBuildFileSection(); - test.ok(buildFileSection[file.uuid] === undefined); + assert.ok(!foundInResourcesBuildPhase); - test.done(); - } -} + const buildFileSection = project.pbxBuildFileSection(); + assert.ok(buildFileSection[file.uuid] === undefined); + }); + }); -exports.removeResourceFileFromGroup = { - 'should add resource file then remove resource file from Localizable.strings group' : function(test) { - var testKey = project.findPBXVariantGroupKey({name:'Localizable.strings'}); - var file = project.addResourceFile('Resources/zh.lproj/Localization.strings', {}, testKey); + describe('removeResourceFileFromGroup', () => { + it('should add resource file then remove resource file from Localizable.strings group', () => { + const testKey = project.findPBXVariantGroupKey({ name: 'Localizable.strings' }); + const file = project.addResourceFile('Resources/zh.lproj/Localization.strings', {}, testKey); - var foundInGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey),file.fileRef ); - test.ok(foundInGroup); + let foundInGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey), file.fileRef); + assert.ok(foundInGroup); - project.removeResourceFile('Resources/zh.lproj/Localization.strings', {}, testKey); + project.removeResourceFile('Resources/zh.lproj/Localization.strings', {}, testKey); - var foundInGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey),file.fileRef ); - test.ok(!foundInGroup); - - test.done(); - } -} + foundInGroup = findChildInGroup(project.getPBXVariantGroupByKey(testKey), file.fileRef); + assert.ok(!foundInGroup); + }); + }); +}); diff --git a/test/xcode5searchPaths.js b/test/xcode5searchPaths.js index 7cdf46ca..8fb971cf 100644 --- a/test/xcode5searchPaths.js +++ b/test/xcode5searchPaths.js @@ -1,75 +1,77 @@ -/** - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - 'License'); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - -var xcode5proj = require('./fixtures/library-search-paths') - xcode5projStr = JSON.stringify(xcode5proj), - pbx = require('../lib/pbxProject'), - pbxFile = require('../lib/pbxFile'), - proj = new pbx('.'), - libPoop = { path: 'some/path/poop.a' }; - -function cleanHash() { +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ + +const { describe, it, beforeEach } = require('node:test'); +const assert = require('node:assert'); + +const xcode5proj = require('./fixtures/library-search-paths'); +const xcode5projStr = JSON.stringify(xcode5proj); +const PBXProject = require('../lib/pbxProject'); +const proj = new PBXProject('.'); +const libPoop = { path: 'some/path/poop.a' }; + +function cleanHash () { return JSON.parse(xcode5projStr); } -exports.setUp = function (callback) { - proj.hash = cleanHash(); - callback(); -} +const PRODUCT_NAME = '"$(TARGET_NAME)"'; -var PRODUCT_NAME = '"$(TARGET_NAME)"'; +describe('addAndRemoveToFromLibrarySearchPaths', () => { + beforeEach(() => { + proj.hash = cleanHash(); + }); -exports.addAndRemoveToFromLibrarySearchPaths = { - 'add should add the path to each configuration section':function(test) { - var expected = '"\\"$(SRCROOT)/$(TARGET_NAME)/some/path\\""', - config = proj.pbxXCBuildConfigurationSection(), - ref, lib, refSettings; + it('add should add the path to each configuration section', () => { + const expected = '"\\"$(SRCROOT)/$(TARGET_NAME)/some/path\\""'; + const config = proj.pbxXCBuildConfigurationSection(); + let ref; + let lib; + let refSettings; proj.addToLibrarySearchPaths(libPoop); for (ref in config) { - if (ref.indexOf('_comment') > -1) - continue; + if (ref.indexOf('_comment') > -1) { continue; } refSettings = config[ref].buildSettings; - if (refSettings.PRODUCT_NAME != PRODUCT_NAME) - continue; + if (refSettings.PRODUCT_NAME !== PRODUCT_NAME) { continue; } lib = refSettings.LIBRARY_SEARCH_PATHS; - test.equal(lib[1], expected); + assert.equal(lib[1], expected); } - test.done(); - }, + }); - 'remove should remove from the path to each configuration section':function(test) { - var config, ref, lib; + it('remove should remove from the path to each configuration section', () => { + let ref; + let lib; proj.addToLibrarySearchPaths(libPoop); proj.removeFromLibrarySearchPaths(libPoop); - config = proj.pbxXCBuildConfigurationSection(); + const config = proj.pbxXCBuildConfigurationSection(); for (ref in config) { - if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME != PRODUCT_NAME) continue; + if (ref.indexOf('_comment') > -1 || config[ref].buildSettings.PRODUCT_NAME !== PRODUCT_NAME) continue; lib = config[ref].buildSettings.LIBRARY_SEARCH_PATHS; - test.ok(lib.length === 1); - test.ok(lib[0].indexOf('$(SRCROOT)/KitchenSinktablet/some/path') == -1); + assert.ok(lib.length === 1); + assert.ok(lib[0].indexOf('$(SRCROOT)/KitchenSinktablet/some/path') === -1); } - test.done(); - } -} + }); +});