From 54c06c43885b9bca09f5c0ec1b9a68de2ee86a78 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 13:56:53 -0300 Subject: [PATCH 01/10] PM-23496 Added and configured Sourcery to automatically generate mocks on build. --- BitwardenShared/Sourcery/Generated/.gitignore | 2 + BitwardenShared/Sourcery/sourcery.yml | 14 ++ Mintfile | 1 + Sourcery/Templates/AutoMockable.stencil | 134 ++++++++++++++++++ project-pm.yml | 8 ++ 5 files changed, 159 insertions(+) create mode 100644 BitwardenShared/Sourcery/Generated/.gitignore create mode 100644 BitwardenShared/Sourcery/sourcery.yml create mode 100644 Sourcery/Templates/AutoMockable.stencil diff --git a/BitwardenShared/Sourcery/Generated/.gitignore b/BitwardenShared/Sourcery/Generated/.gitignore new file mode 100644 index 0000000000..5a0e94031c --- /dev/null +++ b/BitwardenShared/Sourcery/Generated/.gitignore @@ -0,0 +1,2 @@ +# Ignore SwiftGen generated files +*.swift diff --git a/BitwardenShared/Sourcery/sourcery.yml b/BitwardenShared/Sourcery/sourcery.yml new file mode 100644 index 0000000000..d79011a87e --- /dev/null +++ b/BitwardenShared/Sourcery/sourcery.yml @@ -0,0 +1,14 @@ +sources: + - .. + +templates: + - ../../Sourcery/Templates/AutoMockable.stencil + +output: + Generated + +exclude: + - Generated + - Tests + - TestHelpers + - Fixtures \ No newline at end of file diff --git a/Mintfile b/Mintfile index 3a9056208a..0436c70ebf 100644 --- a/Mintfile +++ b/Mintfile @@ -3,3 +3,4 @@ nicklockwood/SwiftFormat@0.56.4 SwiftGen/SwiftGen@6.6.3 realm/SwiftLint@0.59.1 yonaskolb/xcodegen@2.43.0 +krzysztofzablocki/Sourcery@2.2.7 diff --git a/Sourcery/Templates/AutoMockable.stencil b/Sourcery/Templates/AutoMockable.stencil new file mode 100644 index 0000000000..60514ffb7b --- /dev/null +++ b/Sourcery/Templates/AutoMockable.stencil @@ -0,0 +1,134 @@ +// You can ignore local changes using: +// git update-index --assume-unchanged {pathToGeneratedFile}/AutoMockable.generated.swift + +// swiftlint:disable line_length +// swiftlint:disable variable_name + +import BitwardenKit +import BitwardenSdk +import Combine +import Foundation + +{% macro swiftifyMethodName name %}{{ name | replace:"(","_" | replace:")","" | replace:":","_" | replace:"`","" | snakeToCamelCase | lowerFirstWord }}{% endmacro %} + +{% macro methodThrowableErrorDeclaration method %} + var {% call swiftifyMethodName method.selectorName %}Error: Error? +{% endmacro %} + +{% macro methodThrowableErrorUsage method %} + if let error = {% call swiftifyMethodName method.selectorName %}Error { + throw error + } +{% endmacro %} + +{% macro methodReceivedParameters method %} + {%if method.parameters.count == 1 %} + {% set receivedVarName %}{% call swiftifyMethodName method.selectorName %}Received{% for param in method.parameters %}{{ param.name|upperFirstLetter }}{% endfor %}{% endset %} + {{ receivedVarName }}{% for param in method.parameters %} = {{ param.name }}{% endfor %} + {% call swiftifyMethodName method.selectorName %}ReceivedInvocations.append({{ receivedVarName }}!) + {% else %} + {% if not method.parameters.count == 0 %} + {% set receivedVarName %}{% call swiftifyMethodName method.selectorName %}ReceivedArguments{% endset %} + {{ receivedVarName }} = ({% for param in method.parameters %}{{ param.name }}: {{ param.name }}{% if not forloop.last%}, {% endif %}{% endfor %}){% if method.isGeneric %} as? ({% for param in method.parameters %}{{ param.name }}: {% call parameterType param %}{% if not forloop.last%}, {% endif %}{% endfor %}){% endif %} + {% call swiftifyMethodName method.selectorName %}ReceivedInvocations.append({{ receivedVarName }}!) + {% endif %} + {% endif %} +{% endmacro %} + +{% macro methodReturnType method %}{% if method.returnTypeName.isVoid %}Void{% elif method.annotations["GenericReturn"] %}{{ method.annotations["GenericReturn"] }}{% else %}{{ method.returnTypeName }}{% endif %}{% endmacro %} + +{% macro parameterType param %}{% if param.annotations["Generic"] %}{{ param.annotations["Generic"] }}{% else %}{{ param.unwrappedTypeName if param.typeAttributes.escaping else param.typeName }}{% endif %}{% endmacro %} +{% macro parameterArguments param %}{% if param.typeAttributes.escaping %}@escaping {% endif %}{% endmacro %} + +{% macro callClosure method %}return {{ 'try ' if method.throws }}{% if method.isGeneric %}({% endif %}{% call methodClosureName method %}.map({ {{ 'try ' if method.throws }}$0({% call methodClosureCallParameters method %}) }) ?? {% call swiftifyMethodName method.selectorName %}ReturnValue{% if method.isGeneric %}) as! {{ method.returnTypeName }}{% endif %}{% endmacro %} +{% macro methodClosureName method %}{% call swiftifyMethodName method.selectorName %}Closure{% endmacro %} + +{% macro methodClosureDeclaration method %} + var {% call methodClosureName method %}: (({% for param in method.parameters %}{% call parameterArguments param %}{% call parameterType param %}{% if not forloop.last %}, {% endif %}{% endfor %}) {% if method.throws %}throws {% endif %}-> {% if method.isInitializer %}Void{% else %}{% call methodReturnType method %}{% endif %})? +{% endmacro %} + +{% macro methodClosureCallParameters method %}{% for param in method.parameters %}{{ param.name }}{% if not forloop.last %}, {% endif %}{% endfor %}{% endmacro %} +{% macro methodClosureCallParametersFromArguments method %}{% for param in method.parameters %}{% call receivedArgumentsVarName method %}!{% if method.parameters.count > 1 %}.{{ param.name }}{% if not forloop.last %}, {% endif %}{% endif %}{% endfor %}{% endmacro %} + +{% macro receivedArgumentsVarName method %}{% if method.parameters.count == 1 %}{% call swiftifyMethodName method.selectorName %}Received{% for param in method.parameters %}{{ param.name|upperFirstLetter }}{% endfor %}{% else %}{% call swiftifyMethodName method.selectorName %}ReceivedArguments{% endif %}{% endmacro %} + +{% macro mockMethod method %} + //MARK: - {{ method.shortName }} + + {% if method.throws %} + {% call methodThrowableErrorDeclaration method %} + {% endif %} + {% if not method.isInitializer %} + var {% call swiftifyMethodName method.selectorName %}CalledCount = 0 + var {% call swiftifyMethodName method.selectorName %}Called: Bool { + return {% call swiftifyMethodName method.selectorName %}CalledCount > 0 + } + {% endif %} + {% if method.parameters.count == 1 %} + var {% call swiftifyMethodName method.selectorName %}Received{% for param in method.parameters %}{{ param.name|upperFirstLetter }}: {{ '(' if param.isClosure }}{{ param.typeName.unwrappedTypeName }}{{ ')' if param.isClosure }}?{% endfor %} + var {% call swiftifyMethodName method.selectorName %}ReceivedInvocations{% for param in method.parameters %}: [{{ '(' if param.isClosure }}{{ param.typeName.unwrappedTypeName }}{{ ')' if param.isClosure }}{%if param.typeName.isOptional%}?{%endif%}]{% endfor %} = [] + {% elif not method.parameters.count == 0 %} + var {% call swiftifyMethodName method.selectorName %}ReceivedArguments: ({% for param in method.parameters %}{{ param.name }}: {% call parameterType param %}{{ ', ' if not forloop.last }}{% endfor %})? + var {% call swiftifyMethodName method.selectorName %}ReceivedInvocations: [({% for param in method.parameters %}{{ param.name }}: {% call parameterType param %}{{ ', ' if not forloop.last }}{% endfor %})] = [] + {% endif %} + {% if not method.returnTypeName.isVoid and not method.isInitializer %} + var {% call swiftifyMethodName method.selectorName %}ReturnValue: {% call methodReturnType method %}{{ '!' if not method.isOptionalReturnType }} + {% endif %} + {% call methodClosureDeclaration method %} + +{% if method.isInitializer %} + required {{ method.name }} { + {% call methodReceivedParameters method %} + {% call methodClosureName method %}?({% call methodClosureCallParametersFromArguments method %}) + } +{% else %} + func {{ method.name }}{{ ' throws' if method.throws }}{% if not method.returnTypeName.isVoid %} -> {{ method.returnTypeName }}{% endif %} { + {% if method.throws %} + {% call methodThrowableErrorUsage method %} + {% endif %} + {% call swiftifyMethodName method.selectorName %}CalledCount += 1 + {% call methodReceivedParameters method %} + {% if method.returnTypeName.isVoid %} + {% if method.throws %}try {% endif %}{% call methodClosureName method %}?({% call methodClosureCallParametersFromArguments method %}) + {% else %} + {% call callClosure method %} + {% endif %} + } + +{% endif %} +{% endmacro %} + +{% macro mockOptionalVariable variable %} + var {% call mockedVariableName variable %}: {{ variable.typeName }} +{% endmacro %} + +{% macro mockNonOptionalArrayOrDictionaryVariable variable %} + var {% call mockedVariableName variable %}: {{ variable.typeName }} = {% if variable.isArray %}[]{% elif variable.isDictionary %}[:]{% endif %} +{% endmacro %} + +{% macro mockNonOptionalVariable variable %} + var {% call mockedVariableName variable %}: {{ variable.typeName }} { + get { + return {% call underlyingMockedVariableName variable %} + } + set(value) { + {% call underlyingMockedVariableName variable %} = value + } + } + var {% call underlyingMockedVariableName variable %}: {{ variable.typeName }}! +{% endmacro %} + +{% macro underlyingMockedVariableName variable %}underlying{{ variable.name|upperFirstLetter }}{% endmacro %} +{% macro mockedVariableName variable %}{{ variable.name }}{% endmacro %} + +{% for type in types.protocols where type.based.AutoMockable or type|annotated:"AutoMockable" %}{% if type.name != "AutoMockable" %} +class {{ type.name }}Mock: {{ type.name }} { +{% for variable in type.allVariables|!definedInExtension %} + {% if variable.isOptional %}{% call mockOptionalVariable variable %}{% elif variable.isArray or variable.isDictionary %}{% call mockNonOptionalArrayOrDictionaryVariable variable %}{% else %}{% call mockNonOptionalVariable variable %}{% endif %} +{% endfor %} + +{% for method in type.allMethods|!definedInExtension %} + {% call mockMethod method %} +{% endfor %} +} +{% endif %}{% endfor %} \ No newline at end of file diff --git a/project-pm.yml b/project-pm.yml index 679bb92690..0307444d39 100644 --- a/project-pm.yml +++ b/project-pm.yml @@ -391,6 +391,12 @@ targets: - $(SRCROOT)/BitwardenShared/UI/Platform/Application/Support/Generated/Assets.swift - $(SRCROOT)/BitwardenShared/UI/Platform/Application/Support/Generated/Fonts.swift - $(SRCROOT)/BitwardenShared/UI/Platform/Application/Support/Generated/Localizations.swift + - name: Sourcery + script: | + if [[ ! "$PATH" =~ "/opt/homebrew/bin" ]]; then + PATH="/opt/homebrew/bin:$PATH" + fi + mint run sourcery --config BitwardenShared/Sourcery/sourcery.yml BitwardenSharedTests: type: bundle.unit-test platform: iOS @@ -409,6 +415,8 @@ targets: - "**/TestHelpers/*" - "**/Fixtures/*" - path: GlobalTestHelpers + - path: BitwardenShared/Sourcery/Generated + optional: true dependencies: - target: Bitwarden - target: BitwardenShared From 3fd2da8d7ac919c1648d369713a5e7c09fcfa014 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 14:00:29 -0300 Subject: [PATCH 02/10] PM-23496 Fix auto mock stencil and project config to exclude some generated files. --- Sourcery/Templates/AutoMockable.stencil | 5 ++--- project-pm.yml | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sourcery/Templates/AutoMockable.stencil b/Sourcery/Templates/AutoMockable.stencil index 60514ffb7b..70dbb26e2c 100644 --- a/Sourcery/Templates/AutoMockable.stencil +++ b/Sourcery/Templates/AutoMockable.stencil @@ -1,6 +1,3 @@ -// You can ignore local changes using: -// git update-index --assume-unchanged {pathToGeneratedFile}/AutoMockable.generated.swift - // swiftlint:disable line_length // swiftlint:disable variable_name @@ -9,6 +6,8 @@ import BitwardenSdk import Combine import Foundation +@testable import BitwardenShared + {% macro swiftifyMethodName name %}{{ name | replace:"(","_" | replace:")","" | replace:":","_" | replace:"`","" | snakeToCamelCase | lowerFirstWord }}{% endmacro %} {% macro methodThrowableErrorDeclaration method %} diff --git a/project-pm.yml b/project-pm.yml index 0307444d39..e921404965 100644 --- a/project-pm.yml +++ b/project-pm.yml @@ -362,6 +362,7 @@ targets: - "**/TestHelpers/*" - "**/Fixtures/*" - "**/__Snapshots__/*" + - "**/Sourcery/Generated/*" - path: BitwardenShared includes: - "**/__Snapshots__/*" From 523a500da1edd45f4a2f18373df3c0720f21762f Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 14:11:07 -0300 Subject: [PATCH 03/10] PM-23496 Make sure Sourcery is run before bootstrapping to include generate mock files. Somehow they're not automatically included when building in the CI on the test run. --- .github/workflows/test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 91b864fce2..32226b9a8d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -114,6 +114,10 @@ jobs: run: | ./Scripts/update_test_local_config.sh "${{ env._COMPILER_FLAGS }}" + - name: Run Sourcery + run: | + mint run sourcery --config BitwardenShared/Sourcery/sourcery.yml + - name: Install Homebrew Dependencies and run bootstrap.sh run: | brew update From 5ab1cf6de528cc7e806702c73dc00d416c18f923 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 14:28:18 -0300 Subject: [PATCH 04/10] PM-23496 Moved installing Homebrew dependencies earlier in the workflow so it's available for Sourcery. --- .github/workflows/test.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 32226b9a8d..20bdb035f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -114,14 +114,17 @@ jobs: run: | ./Scripts/update_test_local_config.sh "${{ env._COMPILER_FLAGS }}" + - name: Install Homebrew Dependencies + run: | + brew update + brew bundle + - name: Run Sourcery run: | mint run sourcery --config BitwardenShared/Sourcery/sourcery.yml - - name: Install Homebrew Dependencies and run bootstrap.sh + - name: Run bootstrap.sh run: | - brew update - brew bundle ./Scripts/bootstrap.sh - name: Build and test From 3af935c800da9180a803f6ae11b3a7d5c8398af4 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 16:57:54 -0300 Subject: [PATCH 05/10] PM-23496 Fixed Sourcery config based on PR feedback. --- Sourcery/Templates/AutoMockable.stencil | 2 +- project-pm.yml | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Sourcery/Templates/AutoMockable.stencil b/Sourcery/Templates/AutoMockable.stencil index 70dbb26e2c..e765e7aa07 100644 --- a/Sourcery/Templates/AutoMockable.stencil +++ b/Sourcery/Templates/AutoMockable.stencil @@ -121,7 +121,7 @@ import Foundation {% macro mockedVariableName variable %}{{ variable.name }}{% endmacro %} {% for type in types.protocols where type.based.AutoMockable or type|annotated:"AutoMockable" %}{% if type.name != "AutoMockable" %} -class {{ type.name }}Mock: {{ type.name }} { +class Mock{{ type.name }}: {{ type.name }} { {% for variable in type.allVariables|!definedInExtension %} {% if variable.isOptional %}{% call mockOptionalVariable variable %}{% elif variable.isArray or variable.isDictionary %}{% call mockNonOptionalArrayOrDictionaryVariable variable %}{% else %}{% call mockNonOptionalVariable variable %}{% endif %} {% endfor %} diff --git a/project-pm.yml b/project-pm.yml index e921404965..0cbdee2c2b 100644 --- a/project-pm.yml +++ b/project-pm.yml @@ -165,6 +165,8 @@ targets: - path: swiftgen-pm.yml buildPhase: none - path: BitwardenShared/UI/Platform/Application/Support/Localizations # Needed for AppIntent. + - path: BitwardenShared/Sourcery/sourcery.yml + buildPhase: none dependencies: - target: BitwardenShared - target: BitwardenActionExtension @@ -398,6 +400,9 @@ targets: PATH="/opt/homebrew/bin:$PATH" fi mint run sourcery --config BitwardenShared/Sourcery/sourcery.yml + basedOnDependencyAnalysis: false + outputFiles: + - $(SRCROOT)/BitwardenShared/Sourcery/Generated/AutoMockable.generated.swift BitwardenSharedTests: type: bundle.unit-test platform: iOS @@ -418,6 +423,8 @@ targets: - path: GlobalTestHelpers - path: BitwardenShared/Sourcery/Generated optional: true + - path: BitwardenShared/Sourcery/Generated/AutoMockable.generated.swift + optional: true dependencies: - target: Bitwarden - target: BitwardenShared From 719b93cc29a4c827761fbfbf960a87e7e5d189b8 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 16:58:13 -0300 Subject: [PATCH 06/10] Revert "PM-23496 Moved installing Homebrew dependencies earlier in the workflow so it's available for Sourcery." This reverts commit 5ab1cf6de528cc7e806702c73dc00d416c18f923. --- .github/workflows/test.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 20bdb035f3..32226b9a8d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -114,17 +114,14 @@ jobs: run: | ./Scripts/update_test_local_config.sh "${{ env._COMPILER_FLAGS }}" - - name: Install Homebrew Dependencies - run: | - brew update - brew bundle - - name: Run Sourcery run: | mint run sourcery --config BitwardenShared/Sourcery/sourcery.yml - - name: Run bootstrap.sh + - name: Install Homebrew Dependencies and run bootstrap.sh run: | + brew update + brew bundle ./Scripts/bootstrap.sh - name: Build and test From 6ff68527638d958a0ecb0a887a93da19837afe8a Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 16:58:25 -0300 Subject: [PATCH 07/10] Revert "PM-23496 Make sure Sourcery is run before bootstrapping to include generate mock files. Somehow they're not automatically included when building in the CI on the test run." This reverts commit 523a500da1edd45f4a2f18373df3c0720f21762f. --- .github/workflows/test.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 32226b9a8d..91b864fce2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -114,10 +114,6 @@ jobs: run: | ./Scripts/update_test_local_config.sh "${{ env._COMPILER_FLAGS }}" - - name: Run Sourcery - run: | - mint run sourcery --config BitwardenShared/Sourcery/sourcery.yml - - name: Install Homebrew Dependencies and run bootstrap.sh run: | brew update From 35437c58b400d0cd25a495cd76c32300e2a3e26b Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 17:02:48 -0300 Subject: [PATCH 08/10] PM-23496 Adjust sourcery.yml not to appear when copying bundle resources. --- project-pm.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/project-pm.yml b/project-pm.yml index 0cbdee2c2b..7bcee9cb5b 100644 --- a/project-pm.yml +++ b/project-pm.yml @@ -165,8 +165,6 @@ targets: - path: swiftgen-pm.yml buildPhase: none - path: BitwardenShared/UI/Platform/Application/Support/Localizations # Needed for AppIntent. - - path: BitwardenShared/Sourcery/sourcery.yml - buildPhase: none dependencies: - target: BitwardenShared - target: BitwardenActionExtension @@ -365,6 +363,7 @@ targets: - "**/Fixtures/*" - "**/__Snapshots__/*" - "**/Sourcery/Generated/*" + - "**/sourcery.yml" - path: BitwardenShared includes: - "**/__Snapshots__/*" @@ -376,6 +375,8 @@ targets: - path: BitwardenShared/UI/Platform/Application/Support/Generated/Localizations.swift optional: true - path: BitwardenWatchShared + - path: BitwardenShared/Sourcery/sourcery.yml + buildPhase: none dependencies: - package: BitwardenSdk - package: SwiftUIIntrospect From ea2de9b4235a88fc1fd4482e4863c33096215dcc Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 17:12:00 -0300 Subject: [PATCH 09/10] PM-23496 Added Sourcery to BWA shared. --- .../Settings.bundle/Acknowledgements.plist | 8 ++++ .../Acknowledgements/Sourcery.plist | 38 +++++++++++++++++++ .../Sourcery/Generated/.gitignore | 2 + AuthenticatorShared/Sourcery/sourcery.yml | 15 ++++++++ BitwardenShared/Sourcery/sourcery.yml | 3 +- project-bwa.yml | 17 +++++++++ 6 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 Authenticator/Application/Support/Settings.bundle/Acknowledgements/Sourcery.plist create mode 100644 AuthenticatorShared/Sourcery/Generated/.gitignore create mode 100644 AuthenticatorShared/Sourcery/sourcery.yml diff --git a/Authenticator/Application/Support/Settings.bundle/Acknowledgements.plist b/Authenticator/Application/Support/Settings.bundle/Acknowledgements.plist index ce20c864fc..bfb66d92d7 100644 --- a/Authenticator/Application/Support/Settings.bundle/Acknowledgements.plist +++ b/Authenticator/Application/Support/Settings.bundle/Acknowledgements.plist @@ -122,6 +122,14 @@ Type PSChildPaneSpecifier + + File + Acknowledgements/Sourcery + Title + Sourcery + Type + PSChildPaneSpecifier + File Acknowledgements/swift-custom-dump diff --git a/Authenticator/Application/Support/Settings.bundle/Acknowledgements/Sourcery.plist b/Authenticator/Application/Support/Settings.bundle/Acknowledgements/Sourcery.plist new file mode 100644 index 0000000000..51edcbca1b --- /dev/null +++ b/Authenticator/Application/Support/Settings.bundle/Acknowledgements/Sourcery.plist @@ -0,0 +1,38 @@ + + + + + PreferenceSpecifiers + + + FooterText + MIT License + +Copyright (c) 2016-2021 Krzysztof Zabłocki + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + License + MIT + Type + PSGroupSpecifier + + + + diff --git a/AuthenticatorShared/Sourcery/Generated/.gitignore b/AuthenticatorShared/Sourcery/Generated/.gitignore new file mode 100644 index 0000000000..5a0e94031c --- /dev/null +++ b/AuthenticatorShared/Sourcery/Generated/.gitignore @@ -0,0 +1,2 @@ +# Ignore SwiftGen generated files +*.swift diff --git a/AuthenticatorShared/Sourcery/sourcery.yml b/AuthenticatorShared/Sourcery/sourcery.yml new file mode 100644 index 0000000000..1f5739d8dd --- /dev/null +++ b/AuthenticatorShared/Sourcery/sourcery.yml @@ -0,0 +1,15 @@ +sources: + - .. + +templates: + - ../../Sourcery/Templates/AutoMockable.stencil + +output: + Generated + +exclude: + - Generated + - Tests + - TestHelpers + - Fixtures + \ No newline at end of file diff --git a/BitwardenShared/Sourcery/sourcery.yml b/BitwardenShared/Sourcery/sourcery.yml index d79011a87e..1f5739d8dd 100644 --- a/BitwardenShared/Sourcery/sourcery.yml +++ b/BitwardenShared/Sourcery/sourcery.yml @@ -11,4 +11,5 @@ exclude: - Generated - Tests - TestHelpers - - Fixtures \ No newline at end of file + - Fixtures + \ No newline at end of file diff --git a/project-bwa.yml b/project-bwa.yml index 9c5c3fe6db..5499936f1c 100644 --- a/project-bwa.yml +++ b/project-bwa.yml @@ -174,6 +174,8 @@ targets: - "**/TestHelpers/*" - "**/Fixtures/*" - "**/__Snapshots__/*" + - "**/Sourcery/Generated/*" + - "**/sourcery.yml" - path: AuthenticatorShared includes: - "**/__Snapshots__/*" @@ -184,6 +186,8 @@ targets: optional: true - path: AuthenticatorShared/Core/Vault/Services/Importers/Support/Generated/GoogleAuth.pb.swift optional: true + - path: AuthenticatorShared/Sourcery/sourcery.yml + buildPhase: none dependencies: - target: BitwardenKit/AuthenticatorBridgeKit - package: BitwardenSdk @@ -210,6 +214,15 @@ targets: $SRCROOT/AuthenticatorShared/Core/Vault/Services/Importers/Support/GoogleAuth.proto outputFiles: - $(SRCROOT)/AuthenticatorShared/Core/Vault/Services/Importers/Support/Generated/GoogleAuth.pb.swift + - name: Sourcery + script: | + if [[ ! "$PATH" =~ "/opt/homebrew/bin" ]]; then + PATH="/opt/homebrew/bin:$PATH" + fi + mint run sourcery --config AuthenticatorShared/Sourcery/sourcery.yml + basedOnDependencyAnalysis: false + outputFiles: + - $(SRCROOT)/AuthenticatorShared/Sourcery/Generated/AutoMockable.generated.swift AuthenticatorSharedTests: type: bundle.unit-test platform: iOS @@ -225,6 +238,10 @@ targets: - "**/TestHelpers/*" - "**/Fixtures/*" - path: GlobalTestHelpers-bwa + - path: AuthenticatorShared/Sourcery/Generated + optional: true + - path: AuthenticatorShared/Sourcery/Generated/AutoMockable.generated.swift + optional: true dependencies: - target: Authenticator - target: AuthenticatorShared From e0eff3a762c329f0c0c1279d1fee655f04851c87 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 7 Jul 2025 18:26:05 -0300 Subject: [PATCH 10/10] PM-23496 Parametrized the imports in the AutoMockable template. --- AuthenticatorShared/Sourcery/sourcery.yml | 5 ++++- BitwardenShared/Sourcery/sourcery.yml | 5 ++++- Sourcery/Templates/AutoMockable.stencil | 11 +++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/AuthenticatorShared/Sourcery/sourcery.yml b/AuthenticatorShared/Sourcery/sourcery.yml index 1f5739d8dd..f8d6adb8c3 100644 --- a/AuthenticatorShared/Sourcery/sourcery.yml +++ b/AuthenticatorShared/Sourcery/sourcery.yml @@ -12,4 +12,7 @@ exclude: - Tests - TestHelpers - Fixtures - \ No newline at end of file + +args: + autoMockableImports: ["BitwardenKit", "BitwardenSdk", "Combine"] + autoMockableTestableImports: ["AuthenticatorShared"] \ No newline at end of file diff --git a/BitwardenShared/Sourcery/sourcery.yml b/BitwardenShared/Sourcery/sourcery.yml index 1f5739d8dd..5e4c42c2d1 100644 --- a/BitwardenShared/Sourcery/sourcery.yml +++ b/BitwardenShared/Sourcery/sourcery.yml @@ -12,4 +12,7 @@ exclude: - Tests - TestHelpers - Fixtures - \ No newline at end of file + +args: + autoMockableImports: ["BitwardenKit", "BitwardenSdk", "Combine"] + autoMockableTestableImports: ["BitwardenShared"] \ No newline at end of file diff --git a/Sourcery/Templates/AutoMockable.stencil b/Sourcery/Templates/AutoMockable.stencil index e765e7aa07..649205ea99 100644 --- a/Sourcery/Templates/AutoMockable.stencil +++ b/Sourcery/Templates/AutoMockable.stencil @@ -1,12 +1,15 @@ // swiftlint:disable line_length // swiftlint:disable variable_name -import BitwardenKit -import BitwardenSdk -import Combine import Foundation -@testable import BitwardenShared +{% for import in argument.autoMockableImports %} +import {{ import }} +{% endfor %} + +{% for import in argument.autoMockableTestableImports %} +@testable import {{ import }} +{% endfor %} {% macro swiftifyMethodName name %}{{ name | replace:"(","_" | replace:")","" | replace:":","_" | replace:"`","" | snakeToCamelCase | lowerFirstWord }}{% endmacro %}