ViewController.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  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 clearAllCheckFilesItem(_ sender:NSButton) {
  253. DispatchQueue.global().async {
  254. autoreleasepool {
  255. for fileType in testFileTypes {
  256. let types = testTypeInfo[fileType] as! NSArray
  257. for typeInfo in types {
  258. let ti = typeInfo as! NSDictionary
  259. let type = ti["Type"] as! NSString
  260. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  261. if nil != testObject {
  262. testObject?.clearCompareFiles()
  263. }
  264. }
  265. }
  266. DispatchQueue.main.async {
  267. autoreleasepool {
  268. self.reloadListData()
  269. self.advanceView.setAutoTestObj(self.advanceView._autoTestObj)
  270. }
  271. }
  272. }
  273. }
  274. }
  275. @IBAction func clearAllReportItem(_ sender:NSButton) {
  276. DispatchQueue.global().async {
  277. autoreleasepool {
  278. for fileType in testFileTypes {
  279. let types = testTypeInfo[fileType] as! NSArray
  280. for typeInfo in types {
  281. let ti = typeInfo as! NSDictionary
  282. let type = ti["Type"] as! NSString
  283. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  284. if nil != testObject {
  285. testObject?.clearCacheFiles()
  286. }
  287. }
  288. }
  289. DispatchQueue.main.async {
  290. autoreleasepool {
  291. self.reloadListData()
  292. self.advanceView.setAutoTestObj(self.advanceView._autoTestObj)
  293. }
  294. }
  295. }
  296. }
  297. }
  298. @IBAction func diselectAllTestItem(_ sender:NSButton) {
  299. for fileType in testFileTypes {
  300. let types = testTypeInfo[fileType] as! NSArray
  301. for typeInfo in types {
  302. let ti = typeInfo as! NSDictionary
  303. let type = ti["Type"] as! NSString
  304. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  305. if nil != testObject {
  306. testObject?.setSelectedKeys([])
  307. }
  308. }
  309. self.reloadListData()
  310. advanceView.setAutoTestObj(advanceView._autoTestObj)
  311. }
  312. }
  313. @IBAction func showCompareReportAction(_ sender:NSButton) {
  314. let files = NSMutableArray()
  315. for fileType in testFileTypes {
  316. let types = testTypeInfo[fileType] as! NSArray
  317. for typeInfo in types {
  318. let ti = typeInfo as! NSDictionary
  319. let type = ti["Type"] as! NSString
  320. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  321. if (testObject?.selectedKeys().count != 0) {
  322. let tFiles = testObject?.compareFiles();
  323. if (tFiles != nil && tFiles?.count != 0) {
  324. files.addObjects(from: tFiles as! [Any])
  325. }
  326. }
  327. }
  328. }
  329. if files.count > 0 {
  330. let compareVC = CompareViewController.shared()
  331. compareVC.setFiles(files)
  332. let point = sender.convert(CGPoint(x: 0, y: 0), to: self.view.window?.contentView ?? self.view)
  333. compareVC.showIn(self.view.window?.contentView ?? self.view, rect: NSRect.init(origin: point, size: sender.frame.size))
  334. }
  335. return
  336. }
  337. @IBAction func showLatestReportAction(_ sender:NSButton) {
  338. latestResultBtn.isHidden = true;
  339. for fileType in testFileTypes {
  340. let types = testTypeInfo[fileType] as! NSArray
  341. for typeInfo in types {
  342. let ti = typeInfo as! NSDictionary
  343. let type = ti["Type"] as! NSString
  344. let testObject = AutoTest.autoTestFor(fileType as NSString, type: type)
  345. if (testObject?.selectedKeys().count ?? 0 > 0) {
  346. testObject?.setStatus(.Finished)
  347. }
  348. }
  349. }
  350. self.reloadListData()
  351. }
  352. // TableView Delegate
  353. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  354. let cellInfo = AutoTestCellInfo.initWithRow(row)
  355. if cellInfo.isFileType() {
  356. let cellView = TestFileTypeCellView.shared()
  357. let title = cellInfo.fileType()
  358. cellView?.setTitle(title)
  359. return cellView
  360. }else {
  361. let cellView = TestCaseCellView.shared()
  362. let autoTestObj = AutoTest.autoTestFor(NSString(string: (cellInfo.fileType())), type:NSString(string: (cellInfo.typeInfo()["Type"] as! String)))
  363. cellView?.setAutoTestObj(autoTestObj);
  364. cellView?.delegate = self;
  365. return cellView
  366. }
  367. }
  368. func selectionShouldChange(in tableView: NSTableView) -> Bool {
  369. return true
  370. }
  371. func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
  372. return true
  373. }
  374. func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
  375. return false
  376. }
  377. func tableView(_ tableView: NSTableView, mouseDownInHeaderOf tableColumn: NSTableColumn) {
  378. }
  379. func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn) {
  380. }
  381. func tableView(_ tableView: NSTableView, didDrag tableColumn: NSTableColumn) {
  382. }
  383. func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
  384. let cellInfo = AutoTestCellInfo.initWithRow(row)
  385. if cellInfo.isFileType() {
  386. return 30
  387. }else {
  388. return 60
  389. }
  390. }
  391. func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
  392. return false
  393. }
  394. func tableView(_ tableView: NSTableView, sizeToFitWidthOfColumn column: Int) -> CGFloat {
  395. return tableView.frame.width
  396. }
  397. func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
  398. return []
  399. }
  400. func tableViewSelectionDidChange(_ notification: Notification) {
  401. if ((notification.object as! NSTableView) == itemsList) {
  402. let selectRow = itemsList.selectedRow
  403. if selectRow != -1 {
  404. let cellInfo = AutoTestCellInfo.initWithRow(selectRow)
  405. if cellInfo.isFileType() {
  406. let isExpend = DataModel.shared.isExpand(cellInfo.fileType())
  407. DataModel.shared.setIsExpand(cellInfo.fileType(), expand: (!isExpend))
  408. itemsList.reloadData()
  409. }else {
  410. self.setCurrentCellInfo(cellInfo)
  411. }
  412. }else {
  413. }
  414. }
  415. }
  416. // TableView Data Source
  417. func numberOfRows(in tableView: NSTableView) -> Int {
  418. var count = testFileTypes.count
  419. for fileType in testFileTypes {
  420. //当前文件类型是否为展开
  421. if (DataModel.shared.isExpand(fileType)) {
  422. let testTypes = testTypeInfo[fileType] as! NSArray
  423. count = count + testTypes.count
  424. }
  425. }
  426. return count
  427. }
  428. /* 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.
  429. */
  430. // func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
  431. // return testCaseNames[row]
  432. // }
  433. // SettingViewConntroller Handle
  434. func settingViewDidFinished() {
  435. reloadListData()
  436. }
  437. //AutoTestAdvanceSettingView Delegate
  438. func advanceSettingDidUpdate(_ settingView: NSView?) {
  439. if (nil != _currentCellInfo) {
  440. itemsList.reloadData(forRowIndexes: IndexSet(integer: IndexSet.Element((_currentCellInfo?._row)!)),
  441. columnIndexes: IndexSet(integer: IndexSet.Element(0)))
  442. }else {
  443. reloadListData()
  444. }
  445. }
  446. //TestCaseCellViewDelegate
  447. func selectKeyDidUpdate(_ cell: NSTableCellView?) {
  448. advanceView._autoTestObj = advanceView._autoTestObj
  449. }
  450. }