Skip to content

Commit

Permalink
fix(ios): enable swift development in Titanium (#11873)
Browse files Browse the repository at this point in the history
Fixes TIMOB-28062
  • Loading branch information
vijaysingh-axway authored Aug 17, 2020
1 parent 4260e91 commit 2b4aa7b
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 70 deletions.
1 change: 0 additions & 1 deletion iphone/Classes/AppModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#ifdef USE_TI_APP

#import "AppModule.h"
#import "TiUtils+Addons.h"
#import <TitaniumKit/ListenerEntry.h>
#import <TitaniumKit/TiApp.h>
#import <TitaniumKit/TiHost.h>
Expand Down
1 change: 0 additions & 1 deletion iphone/Classes/GeolocationModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#ifdef USE_TI_GEOLOCATION

#import "GeolocationModule.h"
#import "TiUtils+Addons.h"
#import <TitaniumKit/APSHTTPClient.h>
#import <TitaniumKit/NSData+Additions.h>
#import <TitaniumKit/TiApp.h>
Expand Down
1 change: 0 additions & 1 deletion iphone/Classes/PlatformModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#import "PlatformModule.h"
#import "TiPlatformDisplayCaps.h"
#import "TiUtils+Addons.h"
#import <TitaniumKit/JSValue+Addons.h>
#import <TitaniumKit/TiApp.h>

Expand Down
25 changes: 0 additions & 25 deletions iphone/Classes/TiUtils+Addons.h

This file was deleted.

27 changes: 0 additions & 27 deletions iphone/Classes/TiUtils+Addons.m

This file was deleted.

33 changes: 33 additions & 0 deletions iphone/Classes/TiUtils+Addons.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2020-present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/

import TitaniumKit

extension TiUtils {

/**
Returns a unique identifier for this app.

This will change upon a fresh install.

@return UUID for this app.
*/
@objc(appIdentifier)
class func appIdentifier() -> String? {
let kAppUUIDString = "com.appcelerator.uuid"
let defaults = UserDefaults.standard
var uid = defaults.string(forKey: kAppUUIDString)

if uid == nil {
uid = TiUtils.createUUID()
defaults.set(uid, forKey: kAppUUIDString)
defaults.synchronize()
}

return uid
}
}
2 changes: 1 addition & 1 deletion iphone/TitaniumKit/TitaniumKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@
"$(PROJECT_DIR)/TitaniumKit/Libraries/APSAnalytics",
"$(PROJECT_DIR)/TitaniumKit/Libraries/APSHTTPClient",
);
ONLY_ACTIVE_ARCH = NO;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "-DTARGET_OS_IPHONE";
OTHER_LDFLAGS = (
"$(inherited)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
Expand All @@ -51,8 +49,6 @@
ReferencedContainer = "container:TitaniumKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
14 changes: 13 additions & 1 deletion iphone/cli/commands/_build.js
Original file line number Diff line number Diff line change
Expand Up @@ -2956,6 +2956,8 @@ iOSBuilder.prototype.createXcodeProject = function createXcodeProject(next) {
obj.path = xobjs.PBXFileReference[id + '_comment'] = '"' + appName + '.entitlements"';
} else if (obj.path === 'Titanium.app') {
obj.path = xobjs.PBXFileReference[id + '_comment'] = '"' + appName + '.app"';
} else if (obj.path === '"Titanium-Bridging-Header.h"') {
obj.path = xobjs.PBXFileReference[id + '_comment'] = `"${scrubbedAppName}-Bridging-Header.h"`;
} else if (relPathRegExp.test(obj.path)) {
obj.path = obj.path.replace(relPathRegExp, '$1');
} else if (obj.path === 'LaunchScreen.storyboard' && appc.version.lt(this.xcodeEnv.version, '7.0.0')) {
Expand Down Expand Up @@ -2994,6 +2996,8 @@ iOSBuilder.prototype.createXcodeProject = function createXcodeProject(next) {
child.comment = '"' + appName + '.entitlements"';
} else if (child.comment === 'LaunchScreen.storyboard' && appc.version.lt(this.xcodeEnv.version, '7.0.0')) {
obj.children.splice(i--, 1);
} else if (child.comment === 'Titanium-Bridging-Header.h') {
child.comment = '"' + scrubbedAppName + '-Bridging-Header.h"';
}
}
}
Expand Down Expand Up @@ -3036,6 +3040,9 @@ iOSBuilder.prototype.createXcodeProject = function createXcodeProject(next) {
if (obj.buildSettings.PRODUCT_NAME === 'Titanium') {
obj.buildSettings.PRODUCT_NAME = '"' + appName + '"';
}
if (obj.buildSettings.SWIFT_OBJC_BRIDGING_HEADER === '"Titanium-Bridging-Header.h"') {
obj.buildSettings.SWIFT_OBJC_BRIDGING_HEADER = `"${scrubbedAppName}-Bridging-Header.h"`;
}
if (Array.isArray(obj.buildSettings.LIBRARY_SEARCH_PATHS)) {
obj.buildSettings.LIBRARY_SEARCH_PATHS.forEach(function (item, i, arr) {
arr[i] = item.replace(relPathRegExp, '$1');
Expand Down Expand Up @@ -4492,7 +4499,7 @@ iOSBuilder.prototype.copyTitaniumiOSFiles = function copyTitaniumiOSFiles() {

const nameChanged = !this.previousBuildManifest || this.tiapp.name !== this.previousBuildManifest.name,
name = this.sanitizedAppName(),
extRegExp = /\.(c|cpp|h|m|mm)$/,
extRegExp = /\.(c|cpp|h|m|mm|swift)$/,

// files to watch for while copying
appFiles = {};
Expand Down Expand Up @@ -4618,6 +4625,11 @@ iOSBuilder.prototype.copyTitaniumiOSFiles = function copyTitaniumiOSFiles() {
path.join(this.platformPath, 'iphone', 'Titanium_Prefix.pch'),
path.join(this.buildDir, name + '_Prefix.pch')
);
copyAndReplaceFile.call(
this,
path.join(this.platformPath, 'iphone', 'Titanium-Bridging-Header.h'),
path.join(this.buildDir, `${name}-Bridging-Header.h`)
);
copyAndReplaceFile.call(
this,
path.join(this.platformPath, 'iphone', 'Titanium.xcodeproj', 'xcshareddata', 'xcschemes', 'Titanium.xcscheme'),
Expand Down
3 changes: 3 additions & 0 deletions iphone/iphone/Titanium-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
20 changes: 14 additions & 6 deletions iphone/iphone/Titanium.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
3A0E54371BE811CD003EE654 /* TiUIiOSMenuPopupProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A0E54361BE811CD003EE654 /* TiUIiOSMenuPopupProxy.m */; };
3A1E40511BEAC73D00943233 /* TiUIiOSMenuPopup.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1E40501BEAC73D00943233 /* TiUIiOSMenuPopup.m */; };
3A275F3E1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A275F3D1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.m */; };
3A38F30424D6EBBD00CC6EFB /* TiUtils+Addons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A38F30324D6EBBD00CC6EFB /* TiUtils+Addons.swift */; };
3A3BBAF51D3E2F0F008450DF /* TiAppiOSUserNotificationCenterProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3BBAF41D3E2F0F008450DF /* TiAppiOSUserNotificationCenterProxy.m */; };
3A5AD7261BB9A6E4005B408B /* TiUIiOSPreviewActionGroupProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A5AD7251BB9A6E4005B408B /* TiUIiOSPreviewActionGroupProxy.m */; };
3A5AD7291BB9BEA8005B408B /* TiUIiOSPreviewContextProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A5AD7281BB9BEA8005B408B /* TiUIiOSPreviewContextProxy.m */; };
Expand All @@ -176,7 +177,6 @@
3AB9137C1BB60F070063A4AD /* TiPreviewingDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB9137B1BB60F070063A4AD /* TiPreviewingDelegate.m */; };
3AB913801BB61FDA0063A4AD /* TiUIiOSPreviewActionProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB9137F1BB61FDA0063A4AD /* TiUIiOSPreviewActionProxy.m */; };
3ABA85AB1D7204B100BCD3F1 /* TiAppiOSSearchQueryProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3ABA85AA1D7204B100BCD3F1 /* TiAppiOSSearchQueryProxy.m */; };
4A4D3A9022C0CE6A003D2DB7 /* TiUtils+Addons.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A4D3A8F22C0CE6A003D2DB7 /* TiUtils+Addons.m */; };
673144D6211DBAD7001BDBF2 /* TiUIApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 673144D5211DBAD7001BDBF2 /* TiUIApplication.m */; };
6CF8E95921CDA58800519245 /* TiUITabbedBarProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6CF8E95821CDA58800519245 /* TiUITabbedBarProxy.m */; };
823CC8AC1B7F0E4D00D220C7 /* WatchSessionModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 823CC8AB1B7F0E4D00D220C7 /* WatchSessionModule.m */; };
Expand Down Expand Up @@ -609,6 +609,7 @@
3A1E40501BEAC73D00943233 /* TiUIiOSMenuPopup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIiOSMenuPopup.m; sourceTree = "<group>"; };
3A275F3C1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiUIActivityIndicatorStyleProxy.h; sourceTree = "<group>"; };
3A275F3D1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIActivityIndicatorStyleProxy.m; sourceTree = "<group>"; };
3A38F30324D6EBBD00CC6EFB /* TiUtils+Addons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TiUtils+Addons.swift"; sourceTree = "<group>"; };
3A3BBAF31D3E2F0F008450DF /* TiAppiOSUserNotificationCenterProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiAppiOSUserNotificationCenterProxy.h; sourceTree = "<group>"; };
3A3BBAF41D3E2F0F008450DF /* TiAppiOSUserNotificationCenterProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiAppiOSUserNotificationCenterProxy.m; sourceTree = "<group>"; };
3A5AD7241BB9A6E4005B408B /* TiUIiOSPreviewActionGroupProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiUIiOSPreviewActionGroupProxy.h; sourceTree = "<group>"; };
Expand All @@ -635,8 +636,6 @@
3AB9137F1BB61FDA0063A4AD /* TiUIiOSPreviewActionProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIiOSPreviewActionProxy.m; sourceTree = "<group>"; };
3ABA85A91D7204B100BCD3F1 /* TiAppiOSSearchQueryProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiAppiOSSearchQueryProxy.h; sourceTree = "<group>"; };
3ABA85AA1D7204B100BCD3F1 /* TiAppiOSSearchQueryProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiAppiOSSearchQueryProxy.m; sourceTree = "<group>"; };
4A4D3A8E22C0CE6A003D2DB7 /* TiUtils+Addons.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TiUtils+Addons.h"; sourceTree = "<group>"; };
4A4D3A8F22C0CE6A003D2DB7 /* TiUtils+Addons.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "TiUtils+Addons.m"; sourceTree = "<group>"; };
50115A9315D5DE0500122055 /* ThirdpartyNS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThirdpartyNS.h; path = ../Classes/ThirdpartyNS.h; sourceTree = SOURCE_ROOT; };
673144D4211DBAD7001BDBF2 /* TiUIApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TiUIApplication.h; path = ../Classes/TiUIApplication.h; sourceTree = "<group>"; };
673144D5211DBAD7001BDBF2 /* TiUIApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TiUIApplication.m; path = ../Classes/TiUIApplication.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -697,6 +696,7 @@
84EB08051A71948C00D35815 /* TiUIiOSSplitWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIiOSSplitWindow.m; sourceTree = "<group>"; };
AD3174C01D015DA9000D5F1A /* TiCalendarAttendee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiCalendarAttendee.h; sourceTree = "<group>"; };
AD3174C11D015DA9000D5F1A /* TiCalendarAttendee.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiCalendarAttendee.m; sourceTree = "<group>"; };
B14703DF24DCE10100E8EBF4 /* Titanium-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Titanium-Bridging-Header.h"; sourceTree = "<group>"; };
B1E5DCF62463401A007817F8 /* TiUIShortcutProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TiUIShortcutProxy.h; sourceTree = "<group>"; };
B1E5DCF72463401A007817F8 /* TiUIShortcutProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TiUIShortcutProxy.m; sourceTree = "<group>"; };
B1E5DCFA24634057007817F8 /* TiUIShortcutItemProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TiUIShortcutItemProxy.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1605,6 +1605,7 @@
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
isa = PBXGroup;
children = (
B14703DF24DCE10100E8EBF4 /* Titanium-Bridging-Header.h */,
673144D4211DBAD7001BDBF2 /* TiUIApplication.h */,
673144D5211DBAD7001BDBF2 /* TiUIApplication.m */,
32CA4F630368D1EE00C91783 /* Titanium_Prefix.pch */,
Expand Down Expand Up @@ -1983,8 +1984,7 @@
children = (
DBF30945210F3B420001F770 /* TiApp+Addons.h */,
DBF30946210F3B420001F770 /* TiApp+Addons.m */,
4A4D3A8E22C0CE6A003D2DB7 /* TiUtils+Addons.h */,
4A4D3A8F22C0CE6A003D2DB7 /* TiUtils+Addons.m */,
3A38F30324D6EBBD00CC6EFB /* TiUtils+Addons.swift */,
DBF30942210F37080001F770 /* TiWindowProxy+Addons.h */,
DBF30943210F37080001F770 /* TiWindowProxy+Addons.m */,
);
Expand Down Expand Up @@ -2037,6 +2037,7 @@
LastUpgradeCheck = 1020;
TargetAttributes = {
1D6058900D05DD3D006BFB54 = {
LastSwiftMigration = 1150;
ProvisioningStyle = Manual;
SystemCapabilities = {
com.apple.BackgroundModes = {
Expand Down Expand Up @@ -2154,6 +2155,7 @@
3A1E40511BEAC73D00943233 /* TiUIiOSMenuPopup.m in Sources */,
84A0100417FC8D3500D4BF94 /* TiGravityBehavior.m in Sources */,
24CA8B79111161FE0084E2DE /* TiUITextFieldProxy.m in Sources */,
3A38F30424D6EBBD00CC6EFB /* TiUtils+Addons.swift in Sources */,
24CA8B7A111161FE0084E2DE /* TiUITextField.m in Sources */,
15CB44151C4ED54E00D81480 /* TiUIiOSSystemButtonProxy.m in Sources */,
24CA8B7B111161FE0084E2DE /* TiUITextAreaProxy.m in Sources */,
Expand Down Expand Up @@ -2202,7 +2204,6 @@
1592CC3A1C496EFB00C3DB83 /* TiUIiOSRowAnimationStyleProxy.m in Sources */,
24CA8BAA111161FE0084E2DE /* TiUIButton.m in Sources */,
24CA8BAC111161FE0084E2DE /* TiUIAlertDialogProxy.m in Sources */,
4A4D3A9022C0CE6A003D2DB7 /* TiUtils+Addons.m in Sources */,
24CA8BAE111161FE0084E2DE /* TiUIActivityIndicatorProxy.m in Sources */,
24CA8BAF111161FE0084E2DE /* TiUIActivityIndicator.m in Sources */,
24CA8BBC111161FE0084E2DE /* TiMediaVideoPlayerProxy.m in Sources */,
Expand Down Expand Up @@ -2374,6 +2375,7 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = NO;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -2404,6 +2406,9 @@
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = com.appcelerator.titanium;
PRODUCT_NAME = Titanium;
SWIFT_OBJC_BRIDGING_HEADER = "Titanium-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
WARNING_CFLAGS = "-Wno-arc-performSelector-leaks";
};
Expand All @@ -2417,6 +2422,7 @@
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = NO;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand Down Expand Up @@ -2445,6 +2451,8 @@
"OTHER_LDFLAGS[sdk=iphonesimulator*]" = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = com.appcelerator.titanium;
PRODUCT_NAME = Titanium;
SWIFT_OBJC_BRIDGING_HEADER = "Titanium-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
WARNING_CFLAGS = "-Wno-arc-performSelector-leaks";
};
Expand Down
17 changes: 15 additions & 2 deletions tests/Resources/ti.platform.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
/* global OS_VERSION_MAJOR, OS_VERSION_MINOR */
/* global OS_VERSION_MAJOR, OS_VERSION_MINOR, OS_IOS */
/* eslint-env mocha */
/* eslint no-unused-expressions: "off" */
'use strict';
Expand Down Expand Up @@ -215,7 +215,13 @@ describe('Titanium.Platform', function () {

it('.id', () => {
should(Ti.Platform).have.readOnlyProperty('id').which.is.a.String();
// TODO Verify format?!
if (OS_IOS) {
const platformId = Ti.Platform.id;
should(platformId).be.a.String();
should(platformId.length).eql(36);
// Verify format using regexp!
platformId.should.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
}
});

it('.locale', () => {
Expand All @@ -225,6 +231,13 @@ describe('Titanium.Platform', function () {

it('.macaddress', () => {
should(Ti.Platform).have.readOnlyProperty('macaddress').which.is.a.String();
if (OS_IOS) {
const macaddress = Ti.Platform.macaddress;
should(macaddress).be.a.String();
should(macaddress.length).eql(36);
// Verify format using regexp!
macaddress.should.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
}
});

it('.manufacturer', () => {
Expand Down

0 comments on commit 2b4aa7b

Please sign in to comment.