diff --git a/.github/workflows/apps_automated_android.yml b/.github/workflows/apps_automated_android.yml index 23aaa687f5..d74a18a95a 100644 --- a/.github/workflows/apps_automated_android.yml +++ b/.github/workflows/apps_automated_android.yml @@ -1,4 +1,7 @@ name: 'apps/automated/android' +permissions: + contents: read + pull-requests: write on: push: @@ -8,6 +11,9 @@ on: pull_request: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true @@ -19,14 +25,20 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: - node-version: 20.10.0 + node-version: 23.5.0 + - name: Derive appropriate SHAs for base and head for `nx affected` commands + uses: nrwl/nx-set-shas@v4 + with: + main-branch-name: 'main' + - uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Install Python uses: actions/setup-python@v5 @@ -36,7 +48,7 @@ jobs: - name: Install NativeScript run: | python3 -m pip install --upgrade pip six - npm i -g nativescript --ignore-scripts --legacy-peer-deps + npm i -g nativescript --ignore-scripts ns usage-reporting disable ns error-reporting disable @@ -57,4 +69,4 @@ jobs: with: api-level: 34 arch: x86_64 - script: node tools/scripts/run-automated.js android + script: npx nx test apps-automated -c=android diff --git a/.github/workflows/apps_automated_ios.yml b/.github/workflows/apps_automated_ios.yml index bc978ed37e..e726f6c25a 100644 --- a/.github/workflows/apps_automated_ios.yml +++ b/.github/workflows/apps_automated_ios.yml @@ -1,4 +1,7 @@ name: 'apps/automated/ios' +permissions: + contents: read + pull-requests: write on: push: @@ -8,33 +11,39 @@ on: pull_request: workflow_dispatch: +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: test-ios: - runs-on: flyci-macos-14-m2 + # runs-on: macos-latest + runs-on: warp-macos-15-arm64-6x steps: - uses: actions/checkout@v4 + # - name: ActionDebugger By Warpbuild + # uses: Warpbuilds/action-debugger@v1.3 + - uses: actions/setup-node@v4 with: - node-version: 20.10.0 + node-version: 23.5.0 - - name: Install Python - uses: actions/setup-python@v4 + - name: Derive appropriate SHAs for base and head for `nx affected` commands + uses: nrwl/nx-set-shas@v4 with: - python-version: '3' + main-branch-name: 'main' - name: Install NativeScript run: | - python3 -m pip install --upgrade pip six - npm i -g nativescript --ignore-scripts --legacy-peer-deps + npm i -g nativescript --ignore-scripts ns usage-reporting disable ns error-reporting disable - ns doctor + # ns doctor - name: Setup run: npm run setup @@ -43,7 +52,10 @@ jobs: run: npx nx run-many --target=test --configuration=ci --projects=core - name: Start iOS Simulator - uses: futureware-tech/simulator-action@v3 + uses: futureware-tech/simulator-action@v4 + with: + model: 'iPhone 16 Pro' + os_version: '18.4' - name: Run tests on iOS Simulator - run: node tools/scripts/run-automated.js ios + run: npx nx test apps-automated -c=ios diff --git a/.github/workflows/npm_release_core.yml b/.github/workflows/npm_release_core.yml index 67e6359f82..6c7e8bea4e 100644 --- a/.github/workflows/npm_release_core.yml +++ b/.github/workflows/npm_release_core.yml @@ -1,4 +1,7 @@ name: '@nativescript/core -> npm' +permissions: + contents: read + pull-requests: write on: push: @@ -9,6 +12,7 @@ on: env: NPM_TAG: 'next' + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} jobs: release: @@ -20,6 +24,11 @@ jobs: - name: Setup run: npm run setup + - name: Derive appropriate SHAs for base and head for `nx affected` commands + uses: nrwl/nx-set-shas@v4 + with: + main-branch-name: 'main' + - name: Generate Version working-directory: packages/core run: | @@ -31,13 +40,13 @@ jobs: # TODO: build ui-mobile-base first - name: Build @nativescript/core - run: npx nx run core:build + run: npx nx run core:build.npm - name: Publish @nativescript/core - working-directory: dist/packages + working-directory: dist/packages/core env: NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} run: | - echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ../../.npmrc + echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc echo "Publishing @nativescript/core@$NPM_VERSION to NPM with tag $NPM_TAG..." - npm publish nativescript-core-$NPM_VERSION.tgz --tag $NPM_TAG + npm publish --tag $NPM_TAG --access public diff --git a/.github/workflows/npm_release_tns_core.yml b/.github/workflows/npm_release_tns_core.yml index 5b3849e1b6..d4551f0464 100644 --- a/.github/workflows/npm_release_tns_core.yml +++ b/.github/workflows/npm_release_tns_core.yml @@ -1,4 +1,7 @@ name: 'tns-core-modules -> npm' +permissions: + contents: read + pull-requests: write on: push: @@ -18,7 +21,7 @@ jobs: - uses: actions/checkout@v2 - name: Setup - run: npm install --legacy-peer-deps + run: npm install - name: Generate Version run: | diff --git a/.github/workflows/npm_release_types.yml b/.github/workflows/npm_release_types.yml index 440df76ad5..3fe4e8f699 100644 --- a/.github/workflows/npm_release_types.yml +++ b/.github/workflows/npm_release_types.yml @@ -1,5 +1,8 @@ # TODO: modify to build android & ios types first and then merge into types name: '@nativescript/types -> npm' +permissions: + contents: read + pull-requests: write on: push: diff --git a/.github/workflows/npm_release_webpack.yml b/.github/workflows/npm_release_webpack.yml index 700aed5222..85c0820e01 100644 --- a/.github/workflows/npm_release_webpack.yml +++ b/.github/workflows/npm_release_webpack.yml @@ -1,4 +1,7 @@ name: '@nativescript/webpack -> npm' +permissions: + contents: read + pull-requests: write on: push: @@ -17,7 +20,7 @@ jobs: - uses: actions/checkout@v2 - name: Setup - run: npm install --legacy-peer-deps + run: npm install - name: Generate Version working-directory: packages/webpack @@ -32,10 +35,10 @@ jobs: run: npx nx run webpack:build - name: Publish @nativescript/webpack - working-directory: dist/packages + working-directory: dist/packages/webpack5 env: NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} run: | echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ../../.npmrc echo "Publishing @nativescript/webpack@$NPM_VERSION to NPM with tag $NPM_TAG..." - npm publish nativescript-webpack.tgz --tag $NPM_TAG --dry-run + npm publish --tag $NPM_TAG --dry-run diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml new file mode 100644 index 0000000000..837d6bdffb --- /dev/null +++ b/.github/workflows/ossf-scorecard.yml @@ -0,0 +1,78 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '23 13 * * 3' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled. + if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request' + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore + # file_mode: git + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif diff --git a/.gitignore b/.gitignore index 40b510aa45..24b08c83e4 100644 --- a/.gitignore +++ b/.gitignore @@ -57,4 +57,6 @@ Thumbs.db ios-typings-prj .nx/cache -.nx/workspace-data \ No newline at end of file +.nx/workspace-data +vite.config.*.timestamp* +vitest.config.*.timestamp* \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index a3cebf1ec5..abf1181ca3 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,7 +1,4 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - -npx lint-staged +npx lint-staged --allow-empty diff --git a/README.md b/README.md index 87bfd5a6b1..4673180aad 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ We love you and your pull requests 🤗. Please follow our [contributing guide]( - Solid starter: https://nativescript.new/solid - Svelte starter: https://nativescript.new/svelte - Vue starter: https://nativescript.new/vue +- Vue 3 starter: https://nativescript.new/vue3 - [NativeScript on Twitter](http://twitter.com/NativeScript) - [NativeScript on Discord](https://nativescript.org/discord) - [NativeScript on Stack Overflow](http://stackoverflow.com/questions/tagged/nativescript) diff --git a/apps/automated/.npmrc b/apps/automated/.npmrc deleted file mode 100644 index 3b59692060..0000000000 --- a/apps/automated/.npmrc +++ /dev/null @@ -1,6 +0,0 @@ -legacy-peer-deps=true - -# npm 9+ this defaults to `true` meaning `file:` dependencies are packed and then installed -# but since we want to link the source files in this case, we disable this behavior and -# opt to link the dependency as-is instead. (eg. @nativescript/core) -install-links=false diff --git a/apps/automated/package.json b/apps/automated/package.json index 41de6a023d..6b5d728d9d 100644 --- a/apps/automated/package.json +++ b/apps/automated/package.json @@ -13,10 +13,10 @@ "devDependencies": { "@nativescript/android": "~8.8.0", "@nativescript/ios": "~8.8.0", - "@nativescript/visionos": "~8.7.0", - "@nativescript/webpack": "file:../../dist/packages/nativescript-webpack.tgz", + "@nativescript/visionos": "~8.8.0", + "@nativescript/webpack": "file:../../dist/packages/webpack5", "circular-dependency-plugin": "^5.2.2", - "typescript": "~5.4.0" + "typescript": "~5.6.0" }, "gitHead": "c06800e52ee1a184ea2dffd12a6702aaa43be4e3", "readme": "NativeScript Application" diff --git a/apps/automated/project.json b/apps/automated/project.json index 8244cf69af..1043e4d290 100644 --- a/apps/automated/project.json +++ b/apps/automated/project.json @@ -11,53 +11,68 @@ "targets": { "build": { "executor": "@nativescript/nx:build", + "inputs": ["default", "^production"], "options": { "noHmr": true, "production": true, "uglify": true, "release": true, "forDevice": true - } - }, - "ios": { - "executor": "@nativescript/nx:build", - "inputs": ["default", "^production"], - "outputs": [], - "options": { - "noHmr": true, - "platform": "ios" - } + }, + "configurations": {}, + "dependsOn": ["^build"] }, - "vision": { - "executor": "@nativescript/nx:build", + "debug": { + "executor": "@nativescript/nx:debug", "inputs": ["default", "^production"], - "outputs": [], "options": { "noHmr": true, "debug": false, - "platform": "vision" - } + "uglify": false, + "release": false, + "forDevice": false, + "prepare": false + }, + "configurations": {}, + "dependsOn": ["^build"] }, - "android": { - "executor": "@nativescript/nx:build", + "prepare": { + "executor": "@nativescript/nx:prepare", "inputs": ["default", "^production"], - "outputs": [], "options": { "noHmr": true, - "platform": "android" - } + "production": true, + "uglify": true, + "release": true, + "forDevice": true, + "prepare": true + }, + "configurations": {}, + "dependsOn": ["^build"] + }, + "test": { + "executor": "nx:run-commands", + "defaultConfiguration": "ios", + "configurations": { + "ios": { + "commands": ["node tools/scripts/run-automated.js ios"] + }, + "android": { + "commands": ["node tools/scripts/run-automated.js android"] + } + }, + "dependsOn": ["^build"] }, "clean": { - "executor": "@nativescript/nx:build", - "options": { - "clean": true - } + "executor": "@nativescript/nx:clean", + "options": {} }, "lint": { - "executor": "@nrwl/linter:eslint", + "executor": "@nx/eslint:lint", "options": { "lintFilePatterns": ["apps/automated/**/*.ts", "apps/automated/src/**/*.html"] } } - } + }, + "implicitDependencies": ["webpack5"] } diff --git a/apps/automated/src/color/color-tests-common.ts b/apps/automated/src/color/color-tests-common.ts index 18d94bac96..13182f417f 100644 --- a/apps/automated/src/color/color-tests-common.ts +++ b/apps/automated/src/color/color-tests-common.ts @@ -17,6 +17,19 @@ export var test_Hex_Color = function () { TKUnit.assertEqual(color.argb, 0xffff0000, 'Color.argb not properly parsed'); }; +export var test_Hex_rgba_Color = function () { + // >> color-hex-rgba + // Creates the red color + var color = new Color('#FF0000FF'); + // << color-hex-rgba + TKUnit.assertEqual(color.a, 255, 'Color.a not properly parsed'); + TKUnit.assertEqual(color.r, 255, 'Color.r not properly parsed'); + TKUnit.assertEqual(color.g, 0, 'Color.g not properly parsed'); + TKUnit.assertEqual(color.b, 0, 'Color.b not properly parsed'); + TKUnit.assertEqual(color.hex, '#FF0000', 'Color.hex not properly parsed'); + TKUnit.assertEqual(color.argb, 0xffff0000, 'Color.argb not properly parsed'); +}; + export var test_ShortHex_Color = function () { // >> color-hex-short // Creates the color #FF8800 @@ -30,6 +43,19 @@ export var test_ShortHex_Color = function () { TKUnit.assertEqual(color.argb, 0xffff8800, 'Color.argb not properly parsed'); }; +export var test_ShortHex_rgba_Color = function () { + // >> color-hex-short-rgba + // Creates the color #FF8800 + var color = new Color('#F80F'); + // << color-hex-short-rgba + TKUnit.assertEqual(color.a, 255, 'Color.a not properly parsed'); + TKUnit.assertEqual(color.r, 255, 'Color.r not properly parsed'); + TKUnit.assertEqual(color.g, 136, 'Color.g not properly parsed'); // 0x88 == 136 + TKUnit.assertEqual(color.b, 0, 'Color.b not properly parsed'); + TKUnit.assertEqual(color.hex, '#FF8800', 'Color.hex not properly parsed'); + TKUnit.assertEqual(color.argb, 0xffff8800, 'Color.argb not properly parsed'); +}; + export var test_Argb_Color = function () { // >> color-rgb // Creates the color with 100 alpha, 255 red, 100 green, 100 blue @@ -112,7 +138,10 @@ export var test_Color_isValid = function () { var color = new Color('#FF0000'); TKUnit.assertEqual(Color.isValid(color), true, 'Failed to validate color instance'); - TKUnit.assertEqual(Color.isValid('#FF0000'), true, 'Failed to validate hex color'); + TKUnit.assertEqual(Color.isValid('#FFF'), true, 'Failed to validate 3-digit hex color'); + TKUnit.assertEqual(Color.isValid('#FFF0'), true, 'Failed to validate 4-digit hex color'); + TKUnit.assertEqual(Color.isValid('#FF0000'), true, 'Failed to validate 6-digit hex color'); + TKUnit.assertEqual(Color.isValid('#FF000000'), true, 'Failed to validate 8-digit hex color'); TKUnit.assertEqual(Color.isValid('rgb(255, 100, 100)'), true, 'Failed to validate rgb color'); TKUnit.assertEqual(Color.isValid('hsl(50, 50%, 50%)'), true, 'Failed to validate hsl color'); TKUnit.assertEqual(Color.isValid(null) || Color.isValid(undefined), false, 'Failed to invalidate nullish value'); diff --git a/apps/automated/src/test-runner.ts b/apps/automated/src/test-runner.ts index 6990aca1a1..33a4c6858e 100644 --- a/apps/automated/src/test-runner.ts +++ b/apps/automated/src/test-runner.ts @@ -176,6 +176,9 @@ allTests['STYLE'] = styleTests; import * as visualStateTests from './ui/styling/visual-state-tests'; allTests['VISUAL-STATE'] = visualStateTests; +import * as cssKeywordsTests from './ui/styling/css-keywords-tests'; +allTests['CSS-KEYWORDS'] = cssKeywordsTests; + import * as valueSourceTests from './ui/styling/value-source-tests'; allTests['VALUE-SOURCE'] = valueSourceTests; diff --git a/apps/automated/src/ui/animation/animation-tests.ts b/apps/automated/src/ui/animation/animation-tests.ts index ad75839ce4..7a96d2a7a5 100644 --- a/apps/automated/src/ui/animation/animation-tests.ts +++ b/apps/automated/src/ui/animation/animation-tests.ts @@ -79,7 +79,7 @@ export function test_PlayRejectsWhenAlreadyPlayingAnimation(done) { if (e === 'Animation is already playing.') { done(); } - } + }, ); } @@ -164,8 +164,8 @@ export function test_ChainingAnimations(done) { .then(() => label.animate({ translate: { x: 0, y: 0 }, duration: duration })) .then(() => label.animate({ scale: { x: 5, y: 5 }, duration: duration })) .then(() => label.animate({ scale: { x: 1, y: 1 }, duration: duration })) - .then(() => label.animate({ rotate: 180, duration: duration })) - .then(() => label.animate({ rotate: 0, duration: duration })) + .then(() => label.animate({ rotate: { x: 90, y: 0, z: 180 }, duration: duration })) + .then(() => label.animate({ rotate: { x: 0, y: 0, z: 0 }, duration: duration })) .then(() => { //console.log("Animation finished"); // >> (hide) @@ -610,7 +610,7 @@ export function test_PlayPromiseIsResolvedWhenAnimationFinishes(done) { function onRejected(e) { TKUnit.assert(false, 'Animation play promise should be resolved, not rejected.'); done(e); - } + }, ); } @@ -627,7 +627,7 @@ export function test_PlayPromiseIsRejectedWhenAnimationIsCancelled(done) { function onRejected(e) { TKUnit.assert(animation.isPlaying === false, 'Animation.isPlaying should be false when animation play promise is rejected.'); done(); - } + }, ); animation.cancel(); diff --git a/apps/automated/src/ui/button/button-tests.ts b/apps/automated/src/ui/button/button-tests.ts index cc3dfd7036..6161b4feaf 100644 --- a/apps/automated/src/ui/button/button-tests.ts +++ b/apps/automated/src/ui/button/button-tests.ts @@ -274,7 +274,7 @@ export var test_StateHighlighted_also_fires_pressedState = function () { helper.waitUntilLayoutReady(view); - view._goToVisualState('highlighted'); + view._addVisualState('highlighted'); var actualResult = buttonTestsNative.getNativeBackgroundColor(view); TKUnit.assert(actualResult.hex === expectedNormalizedColor, 'Actual: ' + actualResult.hex + '; Expected: ' + expectedNormalizedColor); @@ -291,7 +291,7 @@ export var test_StateHighlighted_also_fires_activeState = function () { helper.waitUntilLayoutReady(view); - view._goToVisualState('highlighted'); + view._addVisualState('highlighted'); var actualResult = buttonTestsNative.getNativeBackgroundColor(view); TKUnit.assert(actualResult.hex === expectedNormalizedColor, 'Actual: ' + actualResult.hex + '; Expected: ' + expectedNormalizedColor); diff --git a/apps/automated/src/ui/image/image-tests.ts b/apps/automated/src/ui/image/image-tests.ts index 0ea34140c8..9be0666b9f 100644 --- a/apps/automated/src/ui/image/image-tests.ts +++ b/apps/automated/src/ui/image/image-tests.ts @@ -1,7 +1,7 @@ import { Image } from '@nativescript/core/ui/image'; import { StackLayout } from '@nativescript/core/ui/layouts/stack-layout'; import { GridLayout } from '@nativescript/core/ui/layouts/grid-layout'; -import { PropertyChangeData } from '@nativescript/core'; +import { PropertyChangeData, Utils } from '@nativescript/core'; import * as utils from '@nativescript/core/utils'; import * as TKUnit from '../../tk-unit'; import { getColor } from '../../ui-helper'; @@ -27,6 +27,8 @@ if (global.isAndroid) { (backgroundModule).initImageCache(Application.android.startActivity, (backgroundModule).CacheMode.memory); // use memory cache only. } +const expectLayoutRequest = __APPLE__ && Utils.SDK_VERSION >= 18; + export const test_Image_Members = function () { const image = new ImageModule.Image(); TKUnit.assert(types.isUndefined(image.src), 'Image.src is defined'); @@ -273,7 +275,11 @@ export const test_SettingImageSourceWhenSizedToParentDoesNotRequestLayout = ios( image.requestLayout = () => (called = true); image.src = '~/assets/logo.png'; - TKUnit.assertFalse(called, 'image.requestLayout should not be called.'); + if (expectLayoutRequest) { + TKUnit.assertTrue(called, 'image.requestLayout should be called.'); + } else { + TKUnit.assertFalse(called, 'image.requestLayout should not be called.'); + } }); export const test_SettingImageSourceWhenFixedWidthAndHeightDoesNotRequestLayout = ios(() => { @@ -291,7 +297,11 @@ export const test_SettingImageSourceWhenFixedWidthAndHeightDoesNotRequestLayout image.requestLayout = () => (called = true); image.src = '~/assets/logo.png'; - TKUnit.assertFalse(called, 'image.requestLayout should not be called.'); + if (expectLayoutRequest) { + TKUnit.assertTrue(called, 'image.requestLayout should be called.'); + } else { + TKUnit.assertFalse(called, 'image.requestLayout should not be called.'); + } }); export const test_SettingImageSourceWhenSizedToContentShouldInvalidate = ios(() => { diff --git a/apps/automated/src/ui/label/label-tests.ts b/apps/automated/src/ui/label/label-tests.ts index 72648865fa..92311ab24d 100644 --- a/apps/automated/src/ui/label/label-tests.ts +++ b/apps/automated/src/ui/label/label-tests.ts @@ -10,7 +10,7 @@ import * as colorModule from '@nativescript/core/color'; import * as utils from '@nativescript/core/utils'; import * as observableModule from '@nativescript/core/data/observable'; import * as bindable from '@nativescript/core/ui/core/bindable'; -import { CoreTypes, Span, FormattedString } from '@nativescript/core'; +import { CoreTypes, Span, FormattedString, Utils } from '@nativescript/core'; import * as labelTestsNative from './label-tests-native'; import * as fs from '@nativescript/core/file-system'; @@ -23,6 +23,8 @@ import * as helper from '../../ui-helper'; const testDir = 'ui/label'; +const expectLayoutRequest = __APPLE__ && Utils.SDK_VERSION >= 18; + export class LabelTest extends testModule.UITest { public create(): LabelModule.Label { const label = new LabelModule.Label(); @@ -633,7 +635,7 @@ export class LabelTest extends testModule.UITest { } public test_SettingTextWhenInFixedSizeGridShouldNotRequestLayout() { - this.requestLayoutFixture(false, '', (label) => { + this.requestLayoutFixture(expectLayoutRequest, '', (label) => { label.textWrap = false; let host = new GridLayout(); host.width = 100; @@ -644,7 +646,7 @@ export class LabelTest extends testModule.UITest { } public test_ChangingTextWhenInFixedSizeGridShouldNotRequestLayout() { - this.requestLayoutFixture(false, 'Hello World', (label) => { + this.requestLayoutFixture(expectLayoutRequest, 'Hello World', (label) => { label.textWrap = false; let host = new GridLayout(); host.width = 100; @@ -655,7 +657,7 @@ export class LabelTest extends testModule.UITest { } public test_SettingTextWhenFixedWidthAndHeightDoesNotRequestLayout() { - this.requestLayoutFixture(false, '', (label) => { + this.requestLayoutFixture(expectLayoutRequest, '', (label) => { label.textWrap = false; let host = new StackLayout(); label.width = 100; @@ -666,7 +668,7 @@ export class LabelTest extends testModule.UITest { } public test_ChangingTextWhenFixedWidthAndHeightDoesNotRequestLayout() { - this.requestLayoutFixture(false, 'Hello World', (label) => { + this.requestLayoutFixture(expectLayoutRequest, 'Hello World', (label) => { label.textWrap = false; let host = new StackLayout(); label.width = 100; @@ -707,7 +709,7 @@ export class LabelTest extends testModule.UITest { } public test_ChangingTextOnSingleLineTextWhenWidthIsSizedToParentAndHeightIsSizedToContentShouldNotRequestLayout() { - this.requestLayoutFixture(false, 'Hello World', (label) => { + this.requestLayoutFixture(expectLayoutRequest, 'Hello World', (label) => { label.textWrap = false; let host = new StackLayout(); host.width = 100; diff --git a/apps/automated/src/ui/layouts/flexbox-layout-tests.ts b/apps/automated/src/ui/layouts/flexbox-layout-tests.ts index 1fd3ba665d..3bbe457cdc 100644 --- a/apps/automated/src/ui/layouts/flexbox-layout-tests.ts +++ b/apps/automated/src/ui/layouts/flexbox-layout-tests.ts @@ -116,7 +116,7 @@ let activity_flex_wrap = () =>