Merge branch 'sk-chrome-xcode-tests'
* sk-chrome-xcode-tests: Actually report test failures when running in Chrome Change RealmReactTests to run with both executors Fix RealmReactTests to work through Chrome Use a default to override Chrome debugging setting Change ReactTests project to 4 space indentation
This commit is contained in:
commit
4d73c13466
|
@ -14,7 +14,7 @@
|
||||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
||||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
||||||
00E356F31AD99517003FC87E /* RealmReactTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* RealmReactTests.m */; };
|
00E356F31AD99517003FC87E /* RealmReactTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* RealmReactTests.m */; };
|
||||||
02409E1E1BCF1F2E005F3B3E /* RealmJSTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02409E1B1BCF1F2E005F3B3E /* RealmJSTests.mm */; settings = {ASSET_TAGS = (); }; };
|
02409E1E1BCF1F2E005F3B3E /* RealmJSTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02409E1B1BCF1F2E005F3B3E /* RealmJSTests.mm */; };
|
||||||
0277991C1BBF3BC600C96559 /* RealmReact.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0277991B1BBF3BB700C96559 /* RealmReact.framework */; };
|
0277991C1BBF3BC600C96559 /* RealmReact.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0277991B1BBF3BB700C96559 /* RealmReact.framework */; };
|
||||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
||||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
||||||
|
@ -167,7 +167,7 @@
|
||||||
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
|
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
|
||||||
00E356EE1AD99517003FC87E /* RealmReactTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmReactTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
00E356EE1AD99517003FC87E /* RealmReactTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmReactTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
00E356F21AD99517003FC87E /* RealmReactTests.m */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = RealmReactTests.m; sourceTree = "<group>"; tabWidth = 4; };
|
00E356F21AD99517003FC87E /* RealmReactTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RealmReactTests.m; sourceTree = "<group>"; };
|
||||||
02409E1A1BCF1F2E005F3B3E /* RealmJSTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJSTests.h; path = ../../../RealmJSTests.h; sourceTree = "<group>"; };
|
02409E1A1BCF1F2E005F3B3E /* RealmJSTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJSTests.h; path = ../../../RealmJSTests.h; sourceTree = "<group>"; };
|
||||||
02409E1B1BCF1F2E005F3B3E /* RealmJSTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJSTests.mm; path = ../../../RealmJSTests.mm; sourceTree = "<group>"; };
|
02409E1B1BCF1F2E005F3B3E /* RealmJSTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJSTests.mm; path = ../../../RealmJSTests.mm; sourceTree = "<group>"; };
|
||||||
027799061BBF3BB700C96559 /* RealmJS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RealmJS.xcodeproj; path = ../../../RealmJS.xcodeproj; sourceTree = "<group>"; };
|
027799061BBF3BB700C96559 /* RealmJS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RealmJS.xcodeproj; path = ../../../RealmJS.xcodeproj; sourceTree = "<group>"; };
|
||||||
|
@ -367,9 +367,7 @@
|
||||||
00E356EF1AD99517003FC87E /* RealmReactTests */,
|
00E356EF1AD99517003FC87E /* RealmReactTests */,
|
||||||
83CBBA001A601CBA00E9B192 /* Products */,
|
83CBBA001A601CBA00E9B192 /* Products */,
|
||||||
);
|
);
|
||||||
indentWidth = 2;
|
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
tabWidth = 2;
|
|
||||||
};
|
};
|
||||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
/**
|
////////////////////////////////////////////////////////////////////////////
|
||||||
* Copyright (c) 2015-present, Facebook, Inc.
|
//
|
||||||
* All rights reserved.
|
// Copyright 2015 Realm Inc.
|
||||||
*
|
//
|
||||||
* This source code is licensed under the BSD-style license found in the
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
// you may not use this file except in compliance with the License.
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
// 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.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,27 @@
|
||||||
/**
|
////////////////////////////////////////////////////////////////////////////
|
||||||
* Copyright (c) 2015-present, Facebook, Inc.
|
//
|
||||||
* All rights reserved.
|
// Copyright 2015 Realm Inc.
|
||||||
*
|
//
|
||||||
* This source code is licensed under the BSD-style license found in the
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* LICENSE file in the root directory of this source tree. An additional grant
|
// you may not use this file except in compliance with the License.
|
||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
// 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.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
#import "RCTRootView.h"
|
#import "RCTRootView.h"
|
||||||
|
|
||||||
@implementation AppDelegate
|
@implementation AppDelegate
|
||||||
|
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
{
|
|
||||||
NSURL *jsCodeLocation;
|
NSURL *jsCodeLocation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +50,7 @@
|
||||||
* see http://facebook.github.io/react-native/docs/runningondevice.html
|
* see http://facebook.github.io/react-native/docs/runningondevice.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||||
|
|
||||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
|
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
|
||||||
moduleName:@"ReactTests"
|
moduleName:@"ReactTests"
|
||||||
|
|
|
@ -19,32 +19,71 @@
|
||||||
#import "RealmJSTests.h"
|
#import "RealmJSTests.h"
|
||||||
#import "Base/RCTJavaScriptExecutor.h"
|
#import "Base/RCTJavaScriptExecutor.h"
|
||||||
#import "Base/RCTBridge.h"
|
#import "Base/RCTBridge.h"
|
||||||
|
#import "Modules/RCTDevMenu.h"
|
||||||
|
|
||||||
|
@import ObjectiveC;
|
||||||
@import RealmReact;
|
@import RealmReact;
|
||||||
|
|
||||||
extern void JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(JSGlobalContextRef ctx, bool includesNativeCallStack);
|
extern void JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(JSGlobalContextRef ctx, bool includesNativeCallStack);
|
||||||
|
|
||||||
static id<RCTJavaScriptExecutor> s_currentJavaScriptExecutor;
|
|
||||||
|
|
||||||
@interface RealmReactTests : RealmJSTests
|
@interface RealmReactTests : RealmJSTests
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface RealmReactChromeTests : RealmReactTests
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation RealmReactTests
|
@implementation RealmReactTests
|
||||||
|
|
||||||
+ (XCTestSuite *)defaultTestSuite {
|
+ (void)load {
|
||||||
NSNotification *notification = [self waitForNotification:RCTJavaScriptDidLoadNotification];
|
// Swap the [RCTDevMenu init] method with [NSObject init] in order to disable RCTDevMenu completely.
|
||||||
RCTBridge *bridge = notification.userInfo[@"bridge"];
|
IMP init = class_getMethodImplementation([NSObject class], @selector(init));
|
||||||
|
class_replaceMethod([RCTDevMenu class], @selector(init), init, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (!bridge) {
|
+ (Class)executorClass {
|
||||||
NSLog(@"No RCTBridge provided by RCTJavaScriptDidLoadNotification");
|
return NSClassFromString(@"RCTContextExecutor");
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)classNameSuffix {
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (id<RCTJavaScriptExecutor>)currentExecutor {
|
||||||
|
Class executorClass = [self executorClass];
|
||||||
|
if (!executorClass) {
|
||||||
|
NSLog(@"%@: Executor class not found", self);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_currentJavaScriptExecutor = [bridge valueForKey:@"javaScriptExecutor"];
|
static RCTBridge *s_bridge;
|
||||||
assert(s_currentJavaScriptExecutor);
|
if (!s_bridge.valid) {
|
||||||
|
NSNotification *notification = [self waitForNotification:RCTJavaScriptDidLoadNotification];;
|
||||||
|
s_bridge = notification.userInfo[@"bridge"];
|
||||||
|
|
||||||
|
if (!s_bridge) {
|
||||||
|
NSLog(@"No RCTBridge provided by RCTJavaScriptDidLoadNotification");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_bridge.executorClass != executorClass) {
|
||||||
|
s_bridge.executorClass = executorClass;
|
||||||
|
[s_bridge reload];
|
||||||
|
|
||||||
|
// The [RCTBridge reload] method does a dispatch_async that we must run before trying again.
|
||||||
|
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||||
|
|
||||||
|
return [self currentExecutor];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [s_bridge valueForKey:@"javaScriptExecutor"];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (XCTestSuite *)defaultTestSuite {
|
||||||
|
id<RCTJavaScriptExecutor> executor = [self currentExecutor];
|
||||||
|
|
||||||
// FIXME: Remove this nonsense once the crashes go away when a test fails!
|
// FIXME: Remove this nonsense once the crashes go away when a test fails!
|
||||||
JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(s_currentJavaScriptExecutor, false);
|
JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(executor, false);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(ctx, false);
|
JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(ctx, false);
|
||||||
}
|
}
|
||||||
|
@ -57,8 +96,16 @@ static id<RCTJavaScriptExecutor> s_currentJavaScriptExecutor;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
XCTestSuite *suite = [super defaultTestSuite];
|
NSString *nameSuffix = [self classNameSuffix];
|
||||||
|
if (nameSuffix.length) {
|
||||||
|
NSMutableDictionary *renamedTestCaseNames = [[NSMutableDictionary alloc] init];
|
||||||
|
for (NSString *name in testCaseNames) {
|
||||||
|
renamedTestCaseNames[[name stringByAppendingString:nameSuffix]] = testCaseNames[name];
|
||||||
|
}
|
||||||
|
testCaseNames = renamedTestCaseNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTestSuite *suite = [super defaultTestSuite];
|
||||||
for (XCTestSuite *testSuite in [self testSuitesFromDictionary:testCaseNames]) {
|
for (XCTestSuite *testSuite in [self testSuitesFromDictionary:testCaseNames]) {
|
||||||
[suite addTest:testSuite];
|
[suite addTest:testSuite];
|
||||||
}
|
}
|
||||||
|
@ -67,50 +114,73 @@ static id<RCTJavaScriptExecutor> s_currentJavaScriptExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSNotification *)waitForNotification:(NSString *)notificationName {
|
+ (NSNotification *)waitForNotification:(NSString *)notificationName {
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
|
||||||
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
|
||||||
|
__block BOOL condition = NO;
|
||||||
__block NSNotification *notification;
|
__block NSNotification *notification;
|
||||||
|
|
||||||
id token = [nc addObserverForName:notificationName object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
id token = [nc addObserverForName:notificationName object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
|
||||||
|
condition = YES;
|
||||||
notification = note;
|
notification = note;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
while (!notification) {
|
[self waitForCondition:&condition];
|
||||||
|
[nc removeObserver:token];
|
||||||
|
|
||||||
|
return notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)waitForCondition:(BOOL *)condition {
|
||||||
|
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
||||||
|
|
||||||
|
while (!*condition) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[nc removeObserver:token];
|
|
||||||
return notification;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)invokeMethod:(NSString *)method inModule:(NSString *)module error:(NSError * __strong *)outError {
|
+ (id)invokeMethod:(NSString *)method inModule:(NSString *)module error:(NSError * __strong *)outError {
|
||||||
|
id<RCTJavaScriptExecutor> executor = [self currentExecutor];
|
||||||
module = [NSString stringWithFormat:@"realm-tests/%@.js", module];
|
module = [NSString stringWithFormat:@"realm-tests/%@.js", module];
|
||||||
|
|
||||||
dispatch_group_t group = dispatch_group_create();
|
__block BOOL condition = NO;
|
||||||
__block id result;
|
__block id result;
|
||||||
|
|
||||||
dispatch_group_enter(group);
|
[executor executeJSCall:module method:method arguments:@[] callback:^(id json, NSError *error) {
|
||||||
|
// The React Native debuggerWorker.js very bizarrely returns an array five empty arrays to signify an error.
|
||||||
|
if ([json isKindOfClass:[NSArray class]] && [json isEqualToArray:@[@[], @[], @[], @[], @[]]]) {
|
||||||
|
json = nil;
|
||||||
|
|
||||||
[s_currentJavaScriptExecutor executeJSCall:module method:method arguments:@[] callback:^(id json, NSError *error) {
|
if (!error) {
|
||||||
|
error = [NSError errorWithDomain:@"JS" code:1 userInfo:@{NSLocalizedDescriptionKey: @"unknown JS error"}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
condition = YES;
|
||||||
result = json;
|
result = json;
|
||||||
|
|
||||||
if (error && outError) {
|
if (error && outError) {
|
||||||
*outError = error;
|
*outError = error;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
dispatch_group_leave(group);
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
[self waitForCondition:&condition];
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)invokeMethod:(NSString *)method {
|
- (void)invokeMethod:(NSString *)method {
|
||||||
|
NSString *module = NSStringFromClass(self.class);
|
||||||
|
NSString *suffix = [self.class classNameSuffix];
|
||||||
|
|
||||||
|
if (suffix.length && [module hasSuffix:suffix]) {
|
||||||
|
module = [module substringToIndex:(module.length - suffix.length)];
|
||||||
|
}
|
||||||
|
|
||||||
NSError *error;
|
NSError *error;
|
||||||
[self.class invokeMethod:method inModule:NSStringFromClass(self.class) error:&error];
|
[self.class invokeMethod:method inModule:module error:&error];
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
// TODO: Parse and use localizedFailureReason info once we can source map the failure location in JS.
|
// TODO: Parse and use localizedFailureReason info once we can source map the failure location in JS.
|
||||||
|
@ -119,3 +189,15 @@ static id<RCTJavaScriptExecutor> s_currentJavaScriptExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation RealmReactChromeTests
|
||||||
|
|
||||||
|
+ (Class)executorClass {
|
||||||
|
return NSClassFromString(@"RCTWebSocketExecutor");
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString *)classNameSuffix {
|
||||||
|
return @"_Chrome";
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
Loading…
Reference in New Issue