Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add privacy-manifest config support #1406

Merged
merged 10 commits into from
Mar 13, 2024
35 changes: 35 additions & 0 deletions lib/PlatformConfigParser.js
Original file line number Diff line number Diff line change
@@ -0,0 +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.
*/

'use strict';
erisu marked this conversation as resolved.
Show resolved Hide resolved

const ConfigParser = require('cordova-common').ConfigParser;

class PlatformConfigParser extends ConfigParser {
/** getPrivacyManifest */
getPrivacyManifest () {
const platform_manifest = this.doc.find('./platform[@name="ios"]/privacy-manifest');
if (platform_manifest != null) {
return platform_manifest;
}
return null;
}
breautek marked this conversation as resolved.
Show resolved Hide resolved
}

module.exports = PlatformConfigParser;
40 changes: 37 additions & 3 deletions lib/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@
under the License.
*/

'use strict';

const fs = require('fs-extra');
const path = require('path');
const unorm = require('unorm');
const plist = require('plist');
const et = require('elementtree');
erisu marked this conversation as resolved.
Show resolved Hide resolved
const URL = require('url');
const events = require('cordova-common').events;
const xmlHelpers = require('cordova-common').xmlHelpers;
Expand All @@ -35,6 +34,7 @@ const FileUpdater = require('cordova-common').FileUpdater;
const projectFile = require('./projectFile');
const Podfile = require('./Podfile').Podfile;
const check_reqs = require('./check_reqs');
const PlatformConfigParser = require('./PlatformConfigParser');

// launch storyboard and related constants
const IMAGESET_COMPACT_SIZE_CLASS = 'compact';
Expand All @@ -43,9 +43,16 @@ const CDV_ANY_SIZE_CLASS = 'any';
module.exports.prepare = function (cordovaProject, options) {
const platformJson = PlatformJson.load(this.locations.root, 'ios');
const munger = new PlatformMunger('ios', this.locations.root, platformJson, new PluginInfoProvider());

this._config = updateConfigFile(cordovaProject.projectConfig, munger, this.locations);

const parser = new PlatformConfigParser(cordovaProject.projectConfig.path);
try {
const manifest = parser.getPrivacyManifest();
overwritePrivacyManifest(manifest, this.locations);
} catch (err) {
return Promise.reject(new CordovaError(`Could not parse PrivacyManifest in config.xml: ${err}`));
}

// Update own www dir with project's www assets and plugins' assets and js-files
return updateWww(cordovaProject, this.locations)
// update project according to config.xml changes.
Expand Down Expand Up @@ -87,6 +94,33 @@ module.exports.clean = function (options) {
});
};

/**
* Overwrites the privacy manifest file with the provided manifest or sets the default manifest.
* @param {ElementTree} manifest - The manifest to be written to the privacy manifest file.
* @param {Object} locations - The locations object containing the path to the Xcode Cordova project.
*/
function overwritePrivacyManifest (manifest, locations) {
const privacyManifestDest = path.join(locations.xcodeCordovaProj, 'PrivacyInfo.xcprivacy');
if (manifest != null) {
const XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8"?>\n';
const DOCTYPE = '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n';
const plistElement = et.Element('plist');
plistElement.set('version', '1.0');
const dictElement = et.SubElement(plistElement, 'dict');
manifest.getchildren().forEach((child) => {
dictElement.append(child);
});
const etree = new et.ElementTree(plistElement);
const xmlString = XML_DECLARATION + DOCTYPE + etree.write({ xml_declaration: false });
fs.writeFileSync(privacyManifestDest, xmlString, 'utf-8');
return;
}
// Set default privacy manifest
const defaultPrivacyManifest = path.join(__dirname, '..', 'templates', 'project', '__PROJECT_NAME__', 'PrivacyInfo.xcprivacy');
const xmlString = fs.readFileSync(defaultPrivacyManifest, 'utf8');
fs.writeFileSync(privacyManifestDest, xmlString, 'utf-8');
}

/**
* Updates config files in project based on app's config.xml and config munge,
* generated by plugins.
Expand Down
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
"unorm": "^1.6.0",
"which": "^3.0.1",
"xcode": "^3.0.1",
"xml-escape": "^1.1.0"
"xml-escape": "^1.1.0",
"elementtree": "^0.1.7"
},
"nyc": {
"include": [
Expand Down
23 changes: 23 additions & 0 deletions tests/spec/unit/fixtures/prepare/no-privacy-manifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->

<widget id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>SampleApp</name>
</widget>
56 changes: 56 additions & 0 deletions tests/spec/unit/fixtures/prepare/privacy-manifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->

<widget id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>SampleApp</name>
<platform name="ios">
<privacy-manifest>
<key>NSPrivacyTracking</key>
<true/>
<key>NSPrivacyAccessedAPITypes</key>
<array/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<!-- The value provided by Apple for 'Device ID' data type -->
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>

<!-- Fingerprint Identification SDK does not link the 'Device ID' with user's identity -->
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>

<!-- Fingerprint Identification SDK does not use 'Device ID' for tracking -->
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>

<!-- Fingerprint Identification SDK uses 'Device ID' for App Functionality
(prevent fraud and implement security measures) -->
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
</privacy-manifest>
</platform>
</widget>
40 changes: 40 additions & 0 deletions tests/spec/unit/prepare.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
const rewire = require('rewire');
const prepare = rewire('../../../lib/prepare');
const projectFile = require('../../../lib/projectFile');
const { writeFileSync } = require('fs');

Check failure on line 31 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

'writeFileSync' is assigned a value but never used

Check failure on line 31 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

'writeFileSync' is assigned a value but never used

Check failure on line 31 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

'writeFileSync' is assigned a value but never used

Check failure on line 31 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

'writeFileSync' is assigned a value but never used

Check failure on line 31 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

'writeFileSync' is assigned a value but never used

Check failure on line 31 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

'writeFileSync' is assigned a value but never used
const FileUpdater = require('cordova-common').FileUpdater;

const tmpDir = path.join(__dirname, '../../../tmp');
Expand Down Expand Up @@ -1504,6 +1505,45 @@
expect(plist.build.calls.mostRecent().args[0].CFBundleDisplayName).toEqual('MyApp');
});
});
it('Test#021 : <privacy-manifest> - should write out the privacy manifest ', () => {
plist.parse.and.callThrough();
writeFileSyncSpy.and.callThrough();
const projectRoot = iosProject;
const platformProjDir = path.join(projectRoot, 'platforms', 'ios', 'SampleApp');
const PlatformConfigParser = require('../../../lib/PlatformConfigParser');
const my_config = new PlatformConfigParser(path.join(FIXTURES, 'prepare', 'privacy-manifest.xml'));
const privacyManifest = my_config.getPrivacyManifest();
const overwritePrivacyManifest = prepare.__get__('overwritePrivacyManifest');
overwritePrivacyManifest(privacyManifest, p.locations);
const privacyManifestPathDest = path.join(platformProjDir, 'PrivacyInfo.xcprivacy')

Check failure on line 1518 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

Missing semicolon

Check failure on line 1518 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

Missing semicolon

Check failure on line 1518 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

Missing semicolon

Check failure on line 1518 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

Missing semicolon

Check failure on line 1518 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

Missing semicolon

Check failure on line 1518 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

Missing semicolon
expect(writeFileSyncSpy).toHaveBeenCalledWith(privacyManifestPathDest, jasmine.any(String), 'utf-8');
const xml = writeFileSyncSpy.calls.all()[0].args[1];
const json = plist.parse(xml);
expect(json['NSPrivacyTracking']).toBeTrue();

Check failure on line 1522 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1522 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1522 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1522 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1522 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1522 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

["NSPrivacyTracking"] is better written in dot notation
expect(json['NSPrivacyAccessedAPITypes'].length).toBe(0);

Check failure on line 1523 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1523 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1523 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1523 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1523 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1523 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation
expect(json['NSPrivacyTrackingDomains'].length).toBe(0);

Check failure on line 1524 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1524 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1524 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1524 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1524 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1524 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

["NSPrivacyTrackingDomains"] is better written in dot notation
expect(json['NSPrivacyCollectedDataTypes'].length).toBe(1);

Check failure on line 1525 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

["NSPrivacyCollectedDataTypes"] is better written in dot notation

Check failure on line 1525 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

["NSPrivacyCollectedDataTypes"] is better written in dot notation

Check failure on line 1525 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

["NSPrivacyCollectedDataTypes"] is better written in dot notation

Check failure on line 1525 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

["NSPrivacyCollectedDataTypes"] is better written in dot notation

Check failure on line 1525 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

["NSPrivacyCollectedDataTypes"] is better written in dot notation

Check failure on line 1525 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

["NSPrivacyCollectedDataTypes"] is better written in dot notation
});
it('Test#022 : no <privacy-manifest> - should write out the privacy manifest ', () => {
plist.parse.and.callThrough();
writeFileSyncSpy.and.callThrough();
const projectRoot = iosProject;
const platformProjDir = path.join(projectRoot, 'platforms', 'ios', 'SampleApp');
const PlatformConfigParser = require('../../../lib/PlatformConfigParser');
const my_config = new PlatformConfigParser(path.join(FIXTURES, 'prepare', 'no-privacy-manifest.xml'));
const privacyManifest = my_config.getPrivacyManifest();
const overwritePrivacyManifest = prepare.__get__('overwritePrivacyManifest');
overwritePrivacyManifest(privacyManifest, p.locations);
const privacyManifestPathDest = path.join(platformProjDir, 'PrivacyInfo.xcprivacy')

Check failure on line 1537 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

Missing semicolon

Check failure on line 1537 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

Missing semicolon

Check failure on line 1537 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

Missing semicolon

Check failure on line 1537 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

Missing semicolon

Check failure on line 1537 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

Missing semicolon

Check failure on line 1537 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

Missing semicolon
expect(writeFileSyncSpy).toHaveBeenCalledWith(privacyManifestPathDest, jasmine.any(String), 'utf-8');
const xml = writeFileSyncSpy.calls.all()[0].args[1];
const json = plist.parse(xml);
expect(json['NSPrivacyTracking']).toBeFalse();

Check failure on line 1541 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1541 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1541 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1541 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1541 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

["NSPrivacyTracking"] is better written in dot notation

Check failure on line 1541 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

["NSPrivacyTracking"] is better written in dot notation
expect(json['NSPrivacyAccessedAPITypes'].length).toBe(0);

Check failure on line 1542 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1542 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1542 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1542 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1542 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation

Check failure on line 1542 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

["NSPrivacyAccessedAPITypes"] is better written in dot notation
expect(json['NSPrivacyTrackingDomains'].length).toBe(0);

Check failure on line 1543 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on ubuntu-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1543 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on ubuntu-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1543 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on ubuntu-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1543 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 20.x on macos-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1543 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 18.x on macos-latest

["NSPrivacyTrackingDomains"] is better written in dot notation

Check failure on line 1543 in tests/spec/unit/prepare.spec.js

View workflow job for this annotation

GitHub Actions / NodeJS 16.x on macos-latest

["NSPrivacyTrackingDomains"] is better written in dot notation
expect(json['NSPrivacyCollectedDataTypes'].length).toBe(0);
});

erisu marked this conversation as resolved.
Show resolved Hide resolved
});

describe('<resource-file> tests', () => {
Expand Down
Loading