ViewController.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. //
  2. // ViewController.swift
  3. // KdanAuto
  4. //
  5. // Created by 朱东勇 on 2022/11/17.
  6. //
  7. import Cocoa
  8. import ComPDFKit_Conversion
  9. class ViewController : NSViewController, SettingViewControllerDelegate, AutoTestAdvanceSettingViewDelegate, TestCaseCellViewDelegate,
  10. NSTableViewDelegate, NSTableViewDataSource {
  11. @IBOutlet var customView : NSView!
  12. @IBOutlet var settingVCWindow : NSWindow!
  13. @IBOutlet var settingVC : SettingViewController!
  14. @IBOutlet var itemsList : NSTableView!
  15. var _currentCellInfo : AutoTestCellInfo?
  16. @IBOutlet var advanceView : AutoTestAdvanceSettingView!
  17. @IBOutlet var startBtn : NSButton!
  18. @IBOutlet var replaceAllBtn : NSButton!
  19. @IBOutlet var exportReportBtn : NSButton!
  20. @IBOutlet var advanceBtn : NSButton!
  21. @IBOutlet var latestResultBtn : NSButton!
  22. var operateQueue = OperationQueue()
  23. var _isProcessing : Bool!
  24. var autotestBlock:(NSMutableArray) -> () = { (objects:NSMutableArray) in
  25. };
  26. var _selectFileType : String! = ""
  27. override func viewDidLoad() {
  28. super.viewDidLoad()
  29. customView.wantsLayer = true;
  30. customView.layer?.borderColor = NSColor.lightGray.withAlphaComponent(0.4).cgColor
  31. customView.layer?.borderWidth = 1
  32. advanceView.wantsLayer = true
  33. advanceView.layer?.borderColor = NSColor.lightGray.withAlphaComponent(0.4).cgColor
  34. advanceView.layer?.borderWidth = 1
  35. // Load Infos
  36. let path = Bundle.main.path(forResource: "AutoTestProperty", ofType: "plist")!
  37. let url = URL.init(fileURLWithPath: path, isDirectory: false)
  38. let initInfo = try! NSDictionary.init(contentsOf: url, error: ())
  39. testFileTypes = initInfo.allKeys as [String]
  40. testTypeInfo = initInfo as NSDictionary
  41. //
  42. advanceView.delegate = self;
  43. updateProcessStatus()
  44. self.replaceAllBtn.isEnabled = false;
  45. self.exportReportBtn.isEnabled = false;
  46. DispatchQueue.global().async {
  47. for fileType in testFileTypes {
  48. let types = testTypeInfo[fileType] as! NSArray
  49. for typeInfo in types {
  50. let ti = typeInfo as! NSDictionary
  51. let type = ti["Type"] as! NSString
  52. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  53. if testObject != nil &&
  54. testObject!.canUpdateRefImage() {
  55. DispatchQueue.main.sync {
  56. self.replaceAllBtn.isEnabled = true;
  57. }
  58. break
  59. }
  60. }
  61. }
  62. }
  63. DispatchQueue.main.async {
  64. self.view.window?.title = "KdanAuto:"+CPDFConvertKit.sharedInstance().versionString
  65. }
  66. }
  67. override var representedObject: Any? {
  68. didSet {
  69. // Update the view, if already loaded.
  70. }
  71. }
  72. func reloadListData() {
  73. itemsList.reloadData()
  74. }
  75. // Update
  76. func updateProcessStatus() {
  77. startBtn.wantsLayer = true;
  78. startBtn.layer?.cornerRadius = startBtn.frame.width / 2.0
  79. startBtn.layer?.backgroundColor = NSColor.init(red: 0, green: 0.6, blue: 0.6, alpha: 1).cgColor;
  80. startBtn.contentTintColor = NSColor.white
  81. }
  82. // Setter & Getter
  83. func setCurrentCellInfo(_ cellInfo : AutoTestCellInfo?) {
  84. _currentCellInfo = cellInfo
  85. if (nil != _currentCellInfo) {
  86. let autoTestObj = AutoTest.autoTestFor(NSString(string: (_currentCellInfo?.fileType())!), type:NSString(string: (_currentCellInfo?.typeInfo()["Type"] as! String)))
  87. advanceView.setAutoTestObj(autoTestObj)
  88. }else {
  89. advanceView.setAutoTestObj(nil)
  90. }
  91. }
  92. // IBAction
  93. @IBAction func showSettingVC(_ sender:NSButton) {
  94. let settingVC = SettingViewController.shared()
  95. settingVC.delegate = self
  96. settingVC.show()
  97. }
  98. @IBAction func startAction(_ sender:NSButton) {
  99. let path = DataModel.shared.directoryPath();
  100. if NSString(string: path).isEqual(to: "") || !FileManager.default.fileExists(atPath: path) {
  101. return
  102. }
  103. _isProcessing = true;
  104. updateProcessStatus()
  105. startBtn.isEnabled = false
  106. startBtn.title = "Doing"
  107. exportReportBtn.isEnabled = false;
  108. replaceAllBtn.isEnabled = false;
  109. advanceBtn.isEnabled = false;
  110. DispatchQueue.global().async {
  111. let report = NSMutableAttributedString.init(string: "");
  112. DataModel.shared.generaNewReportID()
  113. TestDegreeManager.shared().clearAllHistory()
  114. let objects = NSMutableArray()
  115. // Update For Waiting
  116. for fileType in testFileTypes {
  117. let types = testTypeInfo[fileType] as! NSArray
  118. for typeInfo in types {
  119. let ti = typeInfo as! NSDictionary
  120. let type = ti["Type"] as! NSString
  121. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  122. testObject?.testlog = { (msg, progress) in
  123. DispatchQueue.main.async {
  124. self.view.window?.title = "\(msg)(\(Int(progress*100))%)";
  125. if (testObject!.isEqual(to: self.advanceView._autoTestObj)) {
  126. self.advanceView.setAutoTestObj(testObject)
  127. }
  128. }
  129. }
  130. if (testObject != nil &&
  131. testObject!.needCompareTest()) {
  132. objects.add(testObject!);
  133. testObject?.setStatus(.Wait)
  134. }
  135. }
  136. DispatchQueue.main.sync {
  137. self.reloadListData()
  138. }
  139. }
  140. var objectIndex = 0
  141. //创建 Block
  142. self.autotestBlock = { (objects:NSMutableArray) in
  143. NSLog("[KdanAuto]Auto Test \(objectIndex)")
  144. if (objectIndex >= objects.count) {
  145. // 所有自动化测试对象均执行完成
  146. do {
  147. let rtfData = try? report.data(from: .init(location: 0, length: report.length),
  148. documentAttributes: [.documentType: NSAttributedString.DocumentType.rtf])
  149. let path = NSString(string: DataModel.shared.directoryPath()).appendingPathComponent("TestReport_\(DataModel.shared.latestReportID() ?? "").rtf")
  150. try? FileManager.default.removeItem(atPath: path);
  151. try? rtfData?.write(to: NSURL.fileURL(withPath: path))
  152. } catch {
  153. }
  154. DispatchQueue.main.async {
  155. self.view.window?.title = "KdanAuto:"+CPDFConvertKit.sharedInstance().versionString
  156. self._isProcessing = false
  157. self.updateProcessStatus()
  158. self.startBtn.isEnabled = true
  159. self.startBtn.title = "Start"
  160. self.replaceAllBtn.isEnabled = true
  161. self.exportReportBtn.isEnabled = true;
  162. self.advanceBtn.isEnabled = true;
  163. TestDegreeManager.shared().saveInfo()
  164. }
  165. return
  166. }
  167. // 执行当前索引自动化测试对象
  168. let testobject = objects.object(at: objectIndex) as! AutoTest
  169. testobject.setStatus(.Process)
  170. // 异步执行自动化测试
  171. var complention:(_ object:AutoTest, _ report:NSAttributedString?) -> () = {(object, inReport) in
  172. };
  173. complention = {(object, inReport) in
  174. if inReport != nil {
  175. // 如果有自动化测试报告,则拼接在后面
  176. report.append(inReport!)
  177. }
  178. if (Thread.isMainThread) {
  179. // 更新当前自动化测试对象状态及相关 UI 状态
  180. object.setStatus(.Finished)
  181. self.reloadListData()
  182. if (self.advanceView.getAutoTestObj() != nil &&
  183. object.isEqual(to: self.advanceView.getAutoTestObj())) {
  184. self.advanceView.setAutoTestObj(self.advanceView.getAutoTestObj());
  185. }
  186. }else {
  187. DispatchQueue.main.sync {
  188. // 更新当前自动化测试对象状态及相关 UI 状态
  189. object.setStatus(.Finished)
  190. self.reloadListData()
  191. if (self.advanceView.getAutoTestObj() != nil &&
  192. object.isEqual(to: self.advanceView.getAutoTestObj())) {
  193. self.advanceView.setAutoTestObj(self.advanceView.getAutoTestObj());
  194. }
  195. }
  196. }
  197. DispatchQueue.global().asyncAfter(deadline: DispatchTime.init(uptimeNanoseconds: 300)) {
  198. autoreleasepool {
  199. // 触发下一个自动化测试对象进入自动化测试
  200. objectIndex += 1
  201. self.autotestBlock(objects)
  202. }
  203. }
  204. };
  205. testobject.autoTest(complention);
  206. }
  207. // 异步第0号位置自动化测试
  208. self.autotestBlock(objects)
  209. }
  210. }
  211. @IBAction func relpaceAllAction(_ sender:NSButton) {
  212. // Replace all refrence images for all type
  213. self.startBtn.isEnabled = false
  214. self.replaceAllBtn.isEnabled = false
  215. DispatchQueue.global().async {
  216. // Update For Waiting
  217. for fileType in testFileTypes {
  218. let types = testTypeInfo[fileType] as! NSArray
  219. for typeInfo in types {
  220. autoreleasepool {
  221. let ti = typeInfo as! NSDictionary
  222. let type = ti["Type"] as! NSString
  223. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  224. testObject?.updateRefImage()
  225. }
  226. }
  227. DispatchQueue.main.sync {
  228. self.reloadListData()
  229. }
  230. }
  231. DispatchQueue.main.async {
  232. self.startBtn.isEnabled = true
  233. self.advanceView.setAutoTestObj(self.advanceView._autoTestObj)
  234. }
  235. }
  236. }
  237. @IBAction func selectAllTestItem(_ sender:NSButton) {
  238. for fileType in testFileTypes {
  239. let types = testTypeInfo[fileType] as! NSArray
  240. for typeInfo in types {
  241. let ti = typeInfo as! NSDictionary
  242. let type = ti["Type"] as! NSString
  243. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  244. if nil != testObject {
  245. testObject?.setSelectedKeys((testObject?.keys())!)
  246. }
  247. }
  248. self.reloadListData()
  249. advanceView.setAutoTestObj(advanceView._autoTestObj)
  250. }
  251. }
  252. @IBAction func diselectAllTestItem(_ sender:NSButton) {
  253. for fileType in testFileTypes {
  254. let types = testTypeInfo[fileType] as! NSArray
  255. for typeInfo in types {
  256. let ti = typeInfo as! NSDictionary
  257. let type = ti["Type"] as! NSString
  258. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  259. if nil != testObject {
  260. testObject?.setSelectedKeys([])
  261. }
  262. }
  263. self.reloadListData()
  264. advanceView.setAutoTestObj(advanceView._autoTestObj)
  265. }
  266. }
  267. @IBAction func showCompareReportAction(_ sender:NSButton) {
  268. let files = NSMutableArray()
  269. for fileType in testFileTypes {
  270. let types = testTypeInfo[fileType] as! NSArray
  271. for typeInfo in types {
  272. let ti = typeInfo as! NSDictionary
  273. let type = ti["Type"] as! NSString
  274. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  275. if (testObject?.selectedKeys().count != 0) {
  276. let tFiles = testObject?.compareFiles();
  277. if (tFiles != nil && tFiles?.count != 0) {
  278. files.addObjects(from: tFiles as! [Any])
  279. }
  280. }
  281. }
  282. }
  283. if files.count > 0 {
  284. let compareVC = CompareViewController.shared()
  285. compareVC.setFiles(files)
  286. let point = sender.convert(CGPoint(x: 0, y: 0), to: self.view.window?.contentView ?? self.view)
  287. compareVC.showIn(self.view.window?.contentView ?? self.view, rect: NSRect.init(origin: point, size: sender.frame.size))
  288. }
  289. return
  290. }
  291. @IBAction func showLatestReportAction(_ sender:NSButton) {
  292. latestResultBtn.isHidden = true;
  293. for fileType in testFileTypes {
  294. let types = testTypeInfo[fileType] as! NSArray
  295. for typeInfo in types {
  296. let ti = typeInfo as! NSDictionary
  297. let type = ti["Type"] as! NSString
  298. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  299. if (testObject?.selectedKeys().count ?? 0 > 0) {
  300. testObject?.setStatus(.Finished)
  301. }
  302. }
  303. }
  304. self.reloadListData()
  305. }
  306. // TableView Delegate
  307. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  308. let cellInfo = AutoTestCellInfo.initWithRow(row)
  309. if cellInfo.isFileType() {
  310. let cellView = TestFileTypeCellView.shared()
  311. let title = cellInfo.fileType()
  312. cellView?.setTitle(title)
  313. return cellView
  314. }else {
  315. let cellView = TestCaseCellView.shared()
  316. let autoTestObj = AutoTest.autoTestFor(NSString(string: (cellInfo.fileType())), type:NSString(string: (cellInfo.typeInfo()["Type"] as! String)))
  317. cellView?.setAutoTestObj(autoTestObj);
  318. cellView?.delegate = self;
  319. return cellView
  320. }
  321. }
  322. func selectionShouldChange(in tableView: NSTableView) -> Bool {
  323. return true
  324. }
  325. func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
  326. return true
  327. }
  328. func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
  329. return false
  330. }
  331. func tableView(_ tableView: NSTableView, mouseDownInHeaderOf tableColumn: NSTableColumn) {
  332. }
  333. func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn) {
  334. }
  335. func tableView(_ tableView: NSTableView, didDrag tableColumn: NSTableColumn) {
  336. }
  337. func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
  338. let cellInfo = AutoTestCellInfo.initWithRow(row)
  339. if cellInfo.isFileType() {
  340. return 30
  341. }else {
  342. return 60
  343. }
  344. }
  345. func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
  346. return false
  347. }
  348. func tableView(_ tableView: NSTableView, sizeToFitWidthOfColumn column: Int) -> CGFloat {
  349. return tableView.frame.width
  350. }
  351. func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
  352. return []
  353. }
  354. func tableViewSelectionDidChange(_ notification: Notification) {
  355. if ((notification.object as! NSTableView) == itemsList) {
  356. let selectRow = itemsList.selectedRow
  357. if selectRow != -1 {
  358. let cellInfo = AutoTestCellInfo.initWithRow(selectRow)
  359. if cellInfo.isFileType() {
  360. let isExpend = DataModel.shared.isExpand(cellInfo.fileType())
  361. DataModel.shared.setIsExpand(cellInfo.fileType(), expand: (!isExpend))
  362. itemsList.reloadData()
  363. }else {
  364. self.setCurrentCellInfo(cellInfo)
  365. }
  366. }else {
  367. }
  368. }
  369. }
  370. // TableView Data Source
  371. func numberOfRows(in tableView: NSTableView) -> Int {
  372. var count = testFileTypes.count
  373. for fileType in testFileTypes {
  374. //当前文件类型是否为展开
  375. if (DataModel.shared.isExpand(fileType)) {
  376. let testTypes = testTypeInfo[fileType] as! NSArray
  377. count = count + testTypes.count
  378. }
  379. }
  380. return count
  381. }
  382. /* This method is required for the "Cell Based" TableView, and is optional for the "View Based" TableView. If implemented in the latter case, the value will be set to the view at a given row/column if the view responds to -setObjectValue: (such as NSControl and NSTableCellView). Note that NSTableCellView does not actually display the objectValue, and its value is to be used for bindings. See NSTableCellView.h for more information.
  383. */
  384. // func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
  385. // return testCaseNames[row]
  386. // }
  387. // SettingViewConntroller Handle
  388. func settingViewDidFinished() {
  389. reloadListData()
  390. }
  391. //AutoTestAdvanceSettingView Delegate
  392. func advanceSettingDidUpdate(_ settingView: NSView?) {
  393. if (nil != _currentCellInfo) {
  394. itemsList.reloadData(forRowIndexes: IndexSet(integer: IndexSet.Element((_currentCellInfo?._row)!)),
  395. columnIndexes: IndexSet(integer: IndexSet.Element(0)))
  396. }else {
  397. reloadListData()
  398. }
  399. }
  400. //TestCaseCellViewDelegate
  401. func selectKeyDidUpdate(_ cell: NSTableCellView?) {
  402. advanceView._autoTestObj = advanceView._autoTestObj
  403. }
  404. }