ViewController.swift 18 KB

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