├── .gitignore
├── Podfile
├── Podfile.lock
├── README.md
├── SimpleNoteStarter.zip
├── SimpleNoteTakingApp.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ └── contents.xcworkspacedata
├── SimpleNoteTakingApp.xcworkspace
└── contents.xcworkspacedata
├── SimpleNoteTakingApp
├── AppDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── Config
│ └── Constants.swift
├── Extensions
│ ├── UIColor+Extensions.swift
│ ├── UIStoryboard+Extensions.swift
│ ├── UITableView+Extensions.swift
│ └── UIViewController+Extensions.swift
├── Info.plist
├── Models
│ └── Note.swift
└── ViewControllers
│ ├── HomeViewController.swift
│ ├── LoginViewController.swift
│ └── NoteViewController.swift
└── SimpleNoteTakingAppTests
├── Extensions
└── KIF+Extensions.swift
├── Features
├── BaseUITests.swift
├── HomeTests.swift
└── LoginTests.swift
├── Info.plist
├── SimpleNoteTakingAppTests-Bridging-Header.h
└── Steps
├── CommonSteps.swift
├── HomeSteps.swift
└── LoginSteps.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | *.pbxuser
7 | !default.pbxuser
8 | *.mode1v3
9 | !default.mode1v3
10 | *.mode2v3
11 | !default.mode2v3
12 | *.perspectivev3
13 | !default.perspectivev3
14 | xcuserdata/
15 | *.xccheckout
16 | profile
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 |
22 | # Bundler
23 | .bundle
24 |
25 | Carthage
26 | Pods/
27 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '9.0'
2 |
3 | target 'SimpleNoteTakingApp' do
4 | use_frameworks!
5 |
6 | pod 'Realm', git: 'https://github.com/realm/realm-cocoa.git', branch: 'master', submodules: true
7 | pod 'RealmSwift', git: 'https://github.com/realm/realm-cocoa.git', branch: 'master', submodules: true
8 |
9 | target 'SimpleNoteTakingAppTests' do
10 | inherit! :search_paths
11 | pod 'KIF', git: 'https://github.com/kif-framework/KIF.git', branch: 'master'
12 | pod 'Nimble', :git => 'https://github.com/Quick/Nimble.git', :commit => 'db706fc'
13 | end
14 |
15 | post_install do |installer|
16 | installer.pods_project.targets.each do |target|
17 | target.build_configurations.each do |config|
18 | config.build_settings['SWIFT_VERSION'] = '3.0'
19 | end
20 | end
21 | end
22 |
23 | end
24 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - KIF (3.5.1):
3 | - KIF/Core (= 3.5.1)
4 | - KIF/Core (3.5.1)
5 | - Nimble (5.0.0-alpha.30p1)
6 | - Realm (2.0.2):
7 | - Realm/Headers (= 2.0.2)
8 | - Realm/Headers (2.0.2)
9 | - RealmSwift (2.0.2):
10 | - Realm (= 2.0.2)
11 |
12 | DEPENDENCIES:
13 | - KIF (from `https://github.com/kif-framework/KIF.git`, branch `master`)
14 | - Nimble (from `https://github.com/Quick/Nimble.git`, commit `db706fc`)
15 | - Realm (from `https://github.com/realm/realm-cocoa.git`, branch `master`)
16 | - RealmSwift (from `https://github.com/realm/realm-cocoa.git`, branch `master`)
17 |
18 | EXTERNAL SOURCES:
19 | KIF:
20 | :branch: master
21 | :git: https://github.com/kif-framework/KIF.git
22 | Nimble:
23 | :commit: db706fc
24 | :git: https://github.com/Quick/Nimble.git
25 | Realm:
26 | :branch: master
27 | :git: https://github.com/realm/realm-cocoa.git
28 | :submodules: true
29 | RealmSwift:
30 | :branch: master
31 | :git: https://github.com/realm/realm-cocoa.git
32 | :submodules: true
33 |
34 | CHECKOUT OPTIONS:
35 | KIF:
36 | :commit: 13f543388167c575d0e47f94f52b0f2c7038ed2c
37 | :git: https://github.com/kif-framework/KIF.git
38 | Nimble:
39 | :commit: db706fc
40 | :git: https://github.com/Quick/Nimble.git
41 | Realm:
42 | :commit: 69b4144c71d0224a82f2948884286906c173c2fc
43 | :git: https://github.com/realm/realm-cocoa.git
44 | :submodules: true
45 | RealmSwift:
46 | :commit: 69b4144c71d0224a82f2948884286906c173c2fc
47 | :git: https://github.com/realm/realm-cocoa.git
48 | :submodules: true
49 |
50 | SPEC CHECKSUMS:
51 | KIF: 082eb65279e51c3092923802849eb796a04982ab
52 | Nimble: c5b995b4cd57789ec44b0cfb79640fc00e61a8c7
53 | Realm: 0f5a194af0b7e6158b83db41b4ee1a00be7ddf1a
54 | RealmSwift: 0eb5070d851cba7c66e841ca756d83609dc78bc8
55 |
56 | PODFILE CHECKSUM: 252b3b12b1328969d4ef2309ecb9af67cce2cbef
57 |
58 | COCOAPODS: 1.0.1
59 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A Simple Note App for demonstrating automated UI testing on iOS
2 |
3 | You probably have heard about automated tests before. People talk about it a lot these days, especially when the topic is about software quality.
4 |
5 | They say that if you don't write any tests for your project, you're in big trouble. It may not affect you at the moment. But in the long run, it would become a huge technical debt.
6 |
7 | That's true.
8 |
9 | Project with no tests is impossibile to maintain when it gets big and there are multiple developers involved. As you change something in the code, things start to break. You don't even know that it breaks until your boss comes to your desk and starts yelling. You know that feeling, right?
10 |
11 | So, it's better to know a thing or two about testing so that you can improve your project quality and also improve yourself as a software engineer.
12 |
13 | There are 2 types of automated tests in iOS:
14 |
15 |
16 | - Unit test:
17 |
18 |
19 | - test a specific case in a class.
20 | - make sure that the class works independently on its own.
21 |
22 | - UI test:
23 |
24 |
25 | - is also called Integration test.
26 | - test user interactions with the app.
27 | - make sure that all classes fit well together.
28 |
29 |
30 |
31 |
32 | For the full tutorial, please refer to the link below:
33 |
34 | http://www.appcoda.com/automated-ui-test
35 |
--------------------------------------------------------------------------------
/SimpleNoteStarter.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appcoda/SimpleNote/9a27d4c94fdc20dba1a000e036824e6ffe989e7a/SimpleNoteStarter.zip
--------------------------------------------------------------------------------
/SimpleNoteTakingApp.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | archiveVersion
6 | 1
7 | classes
8 |
9 | objectVersion
10 | 46
11 | objects
12 |
13 | 060CE08A55E090BD9B062DA2
14 |
15 | children
16 |
17 | 5E0E95450D6880AF7638F8F5
18 | 759F63F7D7423A62927BA011
19 |
20 | isa
21 | PBXGroup
22 | name
23 | Frameworks
24 | sourceTree
25 | <group>
26 |
27 | 08EF98704AF410F61BBA9BD1
28 |
29 | includeInIndex
30 | 1
31 | isa
32 | PBXFileReference
33 | lastKnownFileType
34 | text.xcconfig
35 | name
36 | Pods-SimpleNoteTakingApp.debug.xcconfig
37 | path
38 | Pods/Target Support Files/Pods-SimpleNoteTakingApp/Pods-SimpleNoteTakingApp.debug.xcconfig
39 | sourceTree
40 | <group>
41 |
42 | 0E89A0DB0B1948A8A9D2AE83
43 |
44 | buildActionMask
45 | 2147483647
46 | files
47 |
48 | inputPaths
49 |
50 | isa
51 | PBXShellScriptBuildPhase
52 | name
53 | [CP] Embed Pods Frameworks
54 | outputPaths
55 |
56 | runOnlyForDeploymentPostprocessing
57 | 0
58 | shellPath
59 | /bin/sh
60 | shellScript
61 | "${SRCROOT}/Pods/Target Support Files/Pods-SimpleNoteTakingApp/Pods-SimpleNoteTakingApp-frameworks.sh"
62 |
63 | showEnvVarsInLog
64 | 0
65 |
66 | 18EEB4331DB63DA0008D21CC
67 |
68 | children
69 |
70 | 18EEB4341DB63DA0008D21CC
71 |
72 | isa
73 | PBXGroup
74 | path
75 | Extensions
76 | sourceTree
77 | <group>
78 |
79 | 18EEB4341DB63DA0008D21CC
80 |
81 | fileEncoding
82 | 4
83 | isa
84 | PBXFileReference
85 | lastKnownFileType
86 | sourcecode.swift
87 | path
88 | KIF+Extensions.swift
89 | sourceTree
90 | <group>
91 |
92 | 18EEB4351DB63DA0008D21CC
93 |
94 | children
95 |
96 | 18EEB4361DB63DA0008D21CC
97 | 18EEB4371DB63DA0008D21CC
98 | 18EEB4381DB63DA0008D21CC
99 |
100 | isa
101 | PBXGroup
102 | path
103 | Features
104 | sourceTree
105 | <group>
106 |
107 | 18EEB4361DB63DA0008D21CC
108 |
109 | fileEncoding
110 | 4
111 | isa
112 | PBXFileReference
113 | lastKnownFileType
114 | sourcecode.swift
115 | path
116 | BaseUITests.swift
117 | sourceTree
118 | <group>
119 |
120 | 18EEB4371DB63DA0008D21CC
121 |
122 | fileEncoding
123 | 4
124 | isa
125 | PBXFileReference
126 | lastKnownFileType
127 | sourcecode.swift
128 | path
129 | HomeTests.swift
130 | sourceTree
131 | <group>
132 |
133 | 18EEB4381DB63DA0008D21CC
134 |
135 | fileEncoding
136 | 4
137 | isa
138 | PBXFileReference
139 | lastKnownFileType
140 | sourcecode.swift
141 | path
142 | LoginTests.swift
143 | sourceTree
144 | <group>
145 |
146 | 18EEB4391DB63DA0008D21CC
147 |
148 | fileEncoding
149 | 4
150 | isa
151 | PBXFileReference
152 | lastKnownFileType
153 | sourcecode.c.h
154 | path
155 | SimpleNoteTakingAppTests-Bridging-Header.h
156 | sourceTree
157 | <group>
158 |
159 | 18EEB43A1DB63DA0008D21CC
160 |
161 | children
162 |
163 | 18EEB43B1DB63DA0008D21CC
164 | 18EEB43C1DB63DA0008D21CC
165 | 18EEB43D1DB63DA0008D21CC
166 |
167 | isa
168 | PBXGroup
169 | path
170 | Steps
171 | sourceTree
172 | <group>
173 |
174 | 18EEB43B1DB63DA0008D21CC
175 |
176 | fileEncoding
177 | 4
178 | isa
179 | PBXFileReference
180 | lastKnownFileType
181 | sourcecode.swift
182 | path
183 | CommonSteps.swift
184 | sourceTree
185 | <group>
186 |
187 | 18EEB43C1DB63DA0008D21CC
188 |
189 | fileEncoding
190 | 4
191 | isa
192 | PBXFileReference
193 | lastKnownFileType
194 | sourcecode.swift
195 | path
196 | HomeSteps.swift
197 | sourceTree
198 | <group>
199 |
200 | 18EEB43D1DB63DA0008D21CC
201 |
202 | fileEncoding
203 | 4
204 | isa
205 | PBXFileReference
206 | lastKnownFileType
207 | sourcecode.swift
208 | path
209 | LoginSteps.swift
210 | sourceTree
211 | <group>
212 |
213 | 18EEB43E1DB63DA0008D21CC
214 |
215 | fileRef
216 | 18EEB4341DB63DA0008D21CC
217 | isa
218 | PBXBuildFile
219 |
220 | 18EEB43F1DB63DA0008D21CC
221 |
222 | fileRef
223 | 18EEB4361DB63DA0008D21CC
224 | isa
225 | PBXBuildFile
226 |
227 | 18EEB4401DB63DA0008D21CC
228 |
229 | fileRef
230 | 18EEB4371DB63DA0008D21CC
231 | isa
232 | PBXBuildFile
233 |
234 | 18EEB4411DB63DA0008D21CC
235 |
236 | fileRef
237 | 18EEB4381DB63DA0008D21CC
238 | isa
239 | PBXBuildFile
240 |
241 | 18EEB4421DB63DA0008D21CC
242 |
243 | fileRef
244 | 18EEB43B1DB63DA0008D21CC
245 | isa
246 | PBXBuildFile
247 |
248 | 18EEB4431DB63DA0008D21CC
249 |
250 | fileRef
251 | 18EEB43C1DB63DA0008D21CC
252 | isa
253 | PBXBuildFile
254 |
255 | 18EEB4441DB63DA0008D21CC
256 |
257 | fileRef
258 | 18EEB43D1DB63DA0008D21CC
259 | isa
260 | PBXBuildFile
261 |
262 | 18EEB4451DB63F02008D21CC
263 |
264 | fileEncoding
265 | 4
266 | isa
267 | PBXFileReference
268 | lastKnownFileType
269 | sourcecode.swift
270 | path
271 | UIColor+Extensions.swift
272 | sourceTree
273 | <group>
274 |
275 | 18EEB4461DB63F02008D21CC
276 |
277 | fileRef
278 | 18EEB4451DB63F02008D21CC
279 | isa
280 | PBXBuildFile
281 |
282 | 21A573759537D14B921EB3E5
283 |
284 | buildActionMask
285 | 2147483647
286 | files
287 |
288 | inputPaths
289 |
290 | isa
291 | PBXShellScriptBuildPhase
292 | name
293 | [CP] Copy Pods Resources
294 | outputPaths
295 |
296 | runOnlyForDeploymentPostprocessing
297 | 0
298 | shellPath
299 | /bin/sh
300 | shellScript
301 | "${SRCROOT}/Pods/Target Support Files/Pods-SimpleNoteTakingAppTests/Pods-SimpleNoteTakingAppTests-resources.sh"
302 |
303 | showEnvVarsInLog
304 | 0
305 |
306 | 2787861573BE73ED11C5055A
307 |
308 | fileRef
309 | 5E0E95450D6880AF7638F8F5
310 | isa
311 | PBXBuildFile
312 |
313 | 2BD90F8AC0B31C6DB7A3DFD7
314 |
315 | includeInIndex
316 | 1
317 | isa
318 | PBXFileReference
319 | lastKnownFileType
320 | text.xcconfig
321 | name
322 | Pods-SimpleNoteTakingAppTests.debug.xcconfig
323 | path
324 | Pods/Target Support Files/Pods-SimpleNoteTakingAppTests/Pods-SimpleNoteTakingAppTests.debug.xcconfig
325 | sourceTree
326 | <group>
327 |
328 | 2DB49DEAC0C4217C1693F5C9
329 |
330 | fileRef
331 | 759F63F7D7423A62927BA011
332 | isa
333 | PBXBuildFile
334 |
335 | 5C5AADD9672AD06049495439
336 |
337 | includeInIndex
338 | 1
339 | isa
340 | PBXFileReference
341 | lastKnownFileType
342 | text.xcconfig
343 | name
344 | Pods-SimpleNoteTakingAppTests.release.xcconfig
345 | path
346 | Pods/Target Support Files/Pods-SimpleNoteTakingAppTests/Pods-SimpleNoteTakingAppTests.release.xcconfig
347 | sourceTree
348 | <group>
349 |
350 | 5E0E95450D6880AF7638F8F5
351 |
352 | explicitFileType
353 | wrapper.framework
354 | includeInIndex
355 | 0
356 | isa
357 | PBXFileReference
358 | path
359 | Pods_SimpleNoteTakingApp.framework
360 | sourceTree
361 | BUILT_PRODUCTS_DIR
362 |
363 | 72CDFA668CDF702B7FE001DB
364 |
365 | buildActionMask
366 | 2147483647
367 | files
368 |
369 | inputPaths
370 |
371 | isa
372 | PBXShellScriptBuildPhase
373 | name
374 | [CP] Embed Pods Frameworks
375 | outputPaths
376 |
377 | runOnlyForDeploymentPostprocessing
378 | 0
379 | shellPath
380 | /bin/sh
381 | shellScript
382 | "${SRCROOT}/Pods/Target Support Files/Pods-SimpleNoteTakingAppTests/Pods-SimpleNoteTakingAppTests-frameworks.sh"
383 |
384 | showEnvVarsInLog
385 | 0
386 |
387 | 759F63F7D7423A62927BA011
388 |
389 | explicitFileType
390 | wrapper.framework
391 | includeInIndex
392 | 0
393 | isa
394 | PBXFileReference
395 | path
396 | Pods_SimpleNoteTakingAppTests.framework
397 | sourceTree
398 | BUILT_PRODUCTS_DIR
399 |
400 | 98D18A9B4A5B6B800CD523F6
401 |
402 | buildActionMask
403 | 2147483647
404 | files
405 |
406 | inputPaths
407 |
408 | isa
409 | PBXShellScriptBuildPhase
410 | name
411 | [CP] Check Pods Manifest.lock
412 | outputPaths
413 |
414 | runOnlyForDeploymentPostprocessing
415 | 0
416 | shellPath
417 | /bin/sh
418 | shellScript
419 | diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
420 | if [[ $? != 0 ]] ; then
421 | cat << EOM
422 | error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
423 | EOM
424 | exit 1
425 | fi
426 |
427 | showEnvVarsInLog
428 | 0
429 |
430 | B20011C818B47727914AC427
431 |
432 | includeInIndex
433 | 1
434 | isa
435 | PBXFileReference
436 | lastKnownFileType
437 | text.xcconfig
438 | name
439 | Pods-SimpleNoteTakingApp.release.xcconfig
440 | path
441 | Pods/Target Support Files/Pods-SimpleNoteTakingApp/Pods-SimpleNoteTakingApp.release.xcconfig
442 | sourceTree
443 | <group>
444 |
445 | BD3958C1EB521C3903704132
446 |
447 | buildActionMask
448 | 2147483647
449 | files
450 |
451 | inputPaths
452 |
453 | isa
454 | PBXShellScriptBuildPhase
455 | name
456 | [CP] Check Pods Manifest.lock
457 | outputPaths
458 |
459 | runOnlyForDeploymentPostprocessing
460 | 0
461 | shellPath
462 | /bin/sh
463 | shellScript
464 | diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
465 | if [[ $? != 0 ]] ; then
466 | cat << EOM
467 | error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.
468 | EOM
469 | exit 1
470 | fi
471 |
472 | showEnvVarsInLog
473 | 0
474 |
475 | BE27EEC73A32BAAEE7388A9F
476 |
477 | children
478 |
479 | 08EF98704AF410F61BBA9BD1
480 | B20011C818B47727914AC427
481 | 2BD90F8AC0B31C6DB7A3DFD7
482 | 5C5AADD9672AD06049495439
483 |
484 | isa
485 | PBXGroup
486 | name
487 | Pods
488 | sourceTree
489 | <group>
490 |
491 | E5DF510F84E77A3CDCC1CE86
492 |
493 | buildActionMask
494 | 2147483647
495 | files
496 |
497 | inputPaths
498 |
499 | isa
500 | PBXShellScriptBuildPhase
501 | name
502 | [CP] Copy Pods Resources
503 | outputPaths
504 |
505 | runOnlyForDeploymentPostprocessing
506 | 0
507 | shellPath
508 | /bin/sh
509 | shellScript
510 | "${SRCROOT}/Pods/Target Support Files/Pods-SimpleNoteTakingApp/Pods-SimpleNoteTakingApp-resources.sh"
511 |
512 | showEnvVarsInLog
513 | 0
514 |
515 | F3594B2C1D99FCC70046DA07
516 |
517 | children
518 |
519 | F3594B371D99FCC70046DA07
520 | F3594B4C1D99FCC70046DA07
521 | F3594B361D99FCC70046DA07
522 | BE27EEC73A32BAAEE7388A9F
523 | 060CE08A55E090BD9B062DA2
524 |
525 | isa
526 | PBXGroup
527 | sourceTree
528 | <group>
529 |
530 | F3594B2D1D99FCC70046DA07
531 |
532 | attributes
533 |
534 | LastSwiftUpdateCheck
535 | 0730
536 | LastUpgradeCheck
537 | 0800
538 | ORGANIZATIONNAME
539 | AppCoda
540 | TargetAttributes
541 |
542 | F3594B341D99FCC70046DA07
543 |
544 | CreatedOnToolsVersion
545 | 7.3
546 | LastSwiftMigration
547 | 0800
548 |
549 | F3594B481D99FCC70046DA07
550 |
551 | CreatedOnToolsVersion
552 | 7.3
553 | LastSwiftMigration
554 | 0800
555 | TestTargetID
556 | F3594B341D99FCC70046DA07
557 |
558 |
559 |
560 | buildConfigurationList
561 | F3594B301D99FCC70046DA07
562 | compatibilityVersion
563 | Xcode 3.2
564 | developmentRegion
565 | English
566 | hasScannedForEncodings
567 | 0
568 | isa
569 | PBXProject
570 | knownRegions
571 |
572 | en
573 | Base
574 |
575 | mainGroup
576 | F3594B2C1D99FCC70046DA07
577 | productRefGroup
578 | F3594B361D99FCC70046DA07
579 | projectDirPath
580 |
581 | projectReferences
582 |
583 | projectRoot
584 |
585 | targets
586 |
587 | F3594B341D99FCC70046DA07
588 | F3594B481D99FCC70046DA07
589 |
590 |
591 | F3594B301D99FCC70046DA07
592 |
593 | buildConfigurations
594 |
595 | F3594B501D99FCC70046DA07
596 | F3594B511D99FCC70046DA07
597 |
598 | defaultConfigurationIsVisible
599 | 0
600 | defaultConfigurationName
601 | Release
602 | isa
603 | XCConfigurationList
604 |
605 | F3594B311D99FCC70046DA07
606 |
607 | buildActionMask
608 | 2147483647
609 | files
610 |
611 | F3594B731D9B552D0046DA07
612 | 18EEB4461DB63F02008D21CC
613 | F3594B391D99FCC70046DA07
614 | F3594B751D9B552D0046DA07
615 | F3594B721D9B552D0046DA07
616 | F3594B791D9B552D0046DA07
617 | F3594B781D9B552D0046DA07
618 | F3594B741D9B552D0046DA07
619 | F3594B771D9B552D0046DA07
620 | F3594B761D9B552D0046DA07
621 |
622 | isa
623 | PBXSourcesBuildPhase
624 | runOnlyForDeploymentPostprocessing
625 | 0
626 |
627 | F3594B321D99FCC70046DA07
628 |
629 | buildActionMask
630 | 2147483647
631 | files
632 |
633 | 2787861573BE73ED11C5055A
634 |
635 | isa
636 | PBXFrameworksBuildPhase
637 | runOnlyForDeploymentPostprocessing
638 | 0
639 |
640 | F3594B331D99FCC70046DA07
641 |
642 | buildActionMask
643 | 2147483647
644 | files
645 |
646 | F3594B431D99FCC70046DA07
647 | F3594B401D99FCC70046DA07
648 | F3594B3E1D99FCC70046DA07
649 |
650 | isa
651 | PBXResourcesBuildPhase
652 | runOnlyForDeploymentPostprocessing
653 | 0
654 |
655 | F3594B341D99FCC70046DA07
656 |
657 | buildConfigurationList
658 | F3594B521D99FCC70046DA07
659 | buildPhases
660 |
661 | BD3958C1EB521C3903704132
662 | F3594B311D99FCC70046DA07
663 | F3594B321D99FCC70046DA07
664 | F3594B331D99FCC70046DA07
665 | 0E89A0DB0B1948A8A9D2AE83
666 | E5DF510F84E77A3CDCC1CE86
667 |
668 | buildRules
669 |
670 | dependencies
671 |
672 | isa
673 | PBXNativeTarget
674 | name
675 | SimpleNoteTakingApp
676 | productName
677 | SimpleNoteTakingApp
678 | productReference
679 | F3594B351D99FCC70046DA07
680 | productType
681 | com.apple.product-type.application
682 |
683 | F3594B351D99FCC70046DA07
684 |
685 | explicitFileType
686 | wrapper.application
687 | includeInIndex
688 | 0
689 | isa
690 | PBXFileReference
691 | path
692 | SimpleNoteTakingApp.app
693 | sourceTree
694 | BUILT_PRODUCTS_DIR
695 |
696 | F3594B361D99FCC70046DA07
697 |
698 | children
699 |
700 | F3594B351D99FCC70046DA07
701 | F3594B491D99FCC70046DA07
702 |
703 | isa
704 | PBXGroup
705 | name
706 | Products
707 | sourceTree
708 | <group>
709 |
710 | F3594B371D99FCC70046DA07
711 |
712 | children
713 |
714 | F3594B7A1D9B55400046DA07
715 | F3594B661D9B552D0046DA07
716 | F3594B681D9B552D0046DA07
717 | F3594B6C1D9B552D0046DA07
718 | F3594B6E1D9B552D0046DA07
719 | F3594B3C1D99FCC70046DA07
720 | F3594B381D99FCC70046DA07
721 |
722 | isa
723 | PBXGroup
724 | path
725 | SimpleNoteTakingApp
726 | sourceTree
727 | <group>
728 |
729 | F3594B381D99FCC70046DA07
730 |
731 | isa
732 | PBXFileReference
733 | lastKnownFileType
734 | sourcecode.swift
735 | path
736 | AppDelegate.swift
737 | sourceTree
738 | <group>
739 |
740 | F3594B391D99FCC70046DA07
741 |
742 | fileRef
743 | F3594B381D99FCC70046DA07
744 | isa
745 | PBXBuildFile
746 |
747 | F3594B3C1D99FCC70046DA07
748 |
749 | children
750 |
751 | F3594B3D1D99FCC70046DA07
752 |
753 | isa
754 | PBXVariantGroup
755 | name
756 | Main.storyboard
757 | sourceTree
758 | <group>
759 |
760 | F3594B3D1D99FCC70046DA07
761 |
762 | isa
763 | PBXFileReference
764 | lastKnownFileType
765 | file.storyboard
766 | name
767 | Base
768 | path
769 | Base.lproj/Main.storyboard
770 | sourceTree
771 | <group>
772 |
773 | F3594B3E1D99FCC70046DA07
774 |
775 | fileRef
776 | F3594B3C1D99FCC70046DA07
777 | isa
778 | PBXBuildFile
779 |
780 | F3594B3F1D99FCC70046DA07
781 |
782 | isa
783 | PBXFileReference
784 | lastKnownFileType
785 | folder.assetcatalog
786 | path
787 | Assets.xcassets
788 | sourceTree
789 | <group>
790 |
791 | F3594B401D99FCC70046DA07
792 |
793 | fileRef
794 | F3594B3F1D99FCC70046DA07
795 | isa
796 | PBXBuildFile
797 |
798 | F3594B411D99FCC70046DA07
799 |
800 | children
801 |
802 | F3594B421D99FCC70046DA07
803 |
804 | isa
805 | PBXVariantGroup
806 | name
807 | LaunchScreen.storyboard
808 | sourceTree
809 | <group>
810 |
811 | F3594B421D99FCC70046DA07
812 |
813 | isa
814 | PBXFileReference
815 | lastKnownFileType
816 | file.storyboard
817 | name
818 | Base
819 | path
820 | Base.lproj/LaunchScreen.storyboard
821 | sourceTree
822 | <group>
823 |
824 | F3594B431D99FCC70046DA07
825 |
826 | fileRef
827 | F3594B411D99FCC70046DA07
828 | isa
829 | PBXBuildFile
830 |
831 | F3594B441D99FCC70046DA07
832 |
833 | isa
834 | PBXFileReference
835 | lastKnownFileType
836 | text.plist.xml
837 | path
838 | Info.plist
839 | sourceTree
840 | <group>
841 |
842 | F3594B451D99FCC70046DA07
843 |
844 | buildActionMask
845 | 2147483647
846 | files
847 |
848 | 18EEB4431DB63DA0008D21CC
849 | 18EEB43F1DB63DA0008D21CC
850 | 18EEB4401DB63DA0008D21CC
851 | 18EEB43E1DB63DA0008D21CC
852 | 18EEB4421DB63DA0008D21CC
853 | 18EEB4441DB63DA0008D21CC
854 | 18EEB4411DB63DA0008D21CC
855 |
856 | isa
857 | PBXSourcesBuildPhase
858 | runOnlyForDeploymentPostprocessing
859 | 0
860 |
861 | F3594B461D99FCC70046DA07
862 |
863 | buildActionMask
864 | 2147483647
865 | files
866 |
867 | 2DB49DEAC0C4217C1693F5C9
868 |
869 | isa
870 | PBXFrameworksBuildPhase
871 | runOnlyForDeploymentPostprocessing
872 | 0
873 |
874 | F3594B471D99FCC70046DA07
875 |
876 | buildActionMask
877 | 2147483647
878 | files
879 |
880 | isa
881 | PBXResourcesBuildPhase
882 | runOnlyForDeploymentPostprocessing
883 | 0
884 |
885 | F3594B481D99FCC70046DA07
886 |
887 | buildConfigurationList
888 | F3594B551D99FCC70046DA07
889 | buildPhases
890 |
891 | 98D18A9B4A5B6B800CD523F6
892 | F3594B451D99FCC70046DA07
893 | F3594B461D99FCC70046DA07
894 | F3594B471D99FCC70046DA07
895 | 72CDFA668CDF702B7FE001DB
896 | 21A573759537D14B921EB3E5
897 |
898 | buildRules
899 |
900 | dependencies
901 |
902 | F3594B4B1D99FCC70046DA07
903 |
904 | isa
905 | PBXNativeTarget
906 | name
907 | SimpleNoteTakingAppTests
908 | productName
909 | SimpleNoteTakingAppTests
910 | productReference
911 | F3594B491D99FCC70046DA07
912 | productType
913 | com.apple.product-type.bundle.unit-test
914 |
915 | F3594B491D99FCC70046DA07
916 |
917 | explicitFileType
918 | wrapper.cfbundle
919 | includeInIndex
920 | 0
921 | isa
922 | PBXFileReference
923 | path
924 | SimpleNoteTakingAppTests.xctest
925 | sourceTree
926 | BUILT_PRODUCTS_DIR
927 |
928 | F3594B4A1D99FCC70046DA07
929 |
930 | containerPortal
931 | F3594B2D1D99FCC70046DA07
932 | isa
933 | PBXContainerItemProxy
934 | proxyType
935 | 1
936 | remoteGlobalIDString
937 | F3594B341D99FCC70046DA07
938 | remoteInfo
939 | SimpleNoteTakingApp
940 |
941 | F3594B4B1D99FCC70046DA07
942 |
943 | isa
944 | PBXTargetDependency
945 | target
946 | F3594B341D99FCC70046DA07
947 | targetProxy
948 | F3594B4A1D99FCC70046DA07
949 |
950 | F3594B4C1D99FCC70046DA07
951 |
952 | children
953 |
954 | 18EEB4331DB63DA0008D21CC
955 | 18EEB4351DB63DA0008D21CC
956 | 18EEB4391DB63DA0008D21CC
957 | 18EEB43A1DB63DA0008D21CC
958 | F3594B4F1D99FCC70046DA07
959 |
960 | isa
961 | PBXGroup
962 | path
963 | SimpleNoteTakingAppTests
964 | sourceTree
965 | <group>
966 |
967 | F3594B4F1D99FCC70046DA07
968 |
969 | isa
970 | PBXFileReference
971 | lastKnownFileType
972 | text.plist.xml
973 | path
974 | Info.plist
975 | sourceTree
976 | <group>
977 |
978 | F3594B501D99FCC70046DA07
979 |
980 | buildSettings
981 |
982 | ALWAYS_SEARCH_USER_PATHS
983 | NO
984 | CLANG_ANALYZER_NONNULL
985 | YES
986 | CLANG_CXX_LANGUAGE_STANDARD
987 | gnu++0x
988 | CLANG_CXX_LIBRARY
989 | libc++
990 | CLANG_ENABLE_MODULES
991 | YES
992 | CLANG_ENABLE_OBJC_ARC
993 | YES
994 | CLANG_WARN_BOOL_CONVERSION
995 | YES
996 | CLANG_WARN_CONSTANT_CONVERSION
997 | YES
998 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE
999 | YES_ERROR
1000 | CLANG_WARN_EMPTY_BODY
1001 | YES
1002 | CLANG_WARN_ENUM_CONVERSION
1003 | YES
1004 | CLANG_WARN_INFINITE_RECURSION
1005 | YES
1006 | CLANG_WARN_INT_CONVERSION
1007 | YES
1008 | CLANG_WARN_OBJC_ROOT_CLASS
1009 | YES_ERROR
1010 | CLANG_WARN_SUSPICIOUS_MOVE
1011 | YES
1012 | CLANG_WARN_UNREACHABLE_CODE
1013 | YES
1014 | CLANG_WARN__DUPLICATE_METHOD_MATCH
1015 | YES
1016 | CODE_SIGN_IDENTITY[sdk=iphoneos*]
1017 | iPhone Developer
1018 | COPY_PHASE_STRIP
1019 | NO
1020 | DEBUG_INFORMATION_FORMAT
1021 | dwarf
1022 | ENABLE_STRICT_OBJC_MSGSEND
1023 | YES
1024 | ENABLE_TESTABILITY
1025 | YES
1026 | GCC_C_LANGUAGE_STANDARD
1027 | gnu99
1028 | GCC_DYNAMIC_NO_PIC
1029 | NO
1030 | GCC_NO_COMMON_BLOCKS
1031 | YES
1032 | GCC_OPTIMIZATION_LEVEL
1033 | 0
1034 | GCC_PREPROCESSOR_DEFINITIONS
1035 |
1036 | DEBUG=1
1037 | $(inherited)
1038 |
1039 | GCC_WARN_64_TO_32_BIT_CONVERSION
1040 | YES
1041 | GCC_WARN_ABOUT_RETURN_TYPE
1042 | YES_ERROR
1043 | GCC_WARN_UNDECLARED_SELECTOR
1044 | YES
1045 | GCC_WARN_UNINITIALIZED_AUTOS
1046 | YES_AGGRESSIVE
1047 | GCC_WARN_UNUSED_FUNCTION
1048 | YES
1049 | GCC_WARN_UNUSED_VARIABLE
1050 | YES
1051 | IPHONEOS_DEPLOYMENT_TARGET
1052 | 9.3
1053 | MTL_ENABLE_DEBUG_INFO
1054 | YES
1055 | ONLY_ACTIVE_ARCH
1056 | YES
1057 | SDKROOT
1058 | iphoneos
1059 | SWIFT_OPTIMIZATION_LEVEL
1060 | -Onone
1061 |
1062 | isa
1063 | XCBuildConfiguration
1064 | name
1065 | Debug
1066 |
1067 | F3594B511D99FCC70046DA07
1068 |
1069 | buildSettings
1070 |
1071 | ALWAYS_SEARCH_USER_PATHS
1072 | NO
1073 | CLANG_ANALYZER_NONNULL
1074 | YES
1075 | CLANG_CXX_LANGUAGE_STANDARD
1076 | gnu++0x
1077 | CLANG_CXX_LIBRARY
1078 | libc++
1079 | CLANG_ENABLE_MODULES
1080 | YES
1081 | CLANG_ENABLE_OBJC_ARC
1082 | YES
1083 | CLANG_WARN_BOOL_CONVERSION
1084 | YES
1085 | CLANG_WARN_CONSTANT_CONVERSION
1086 | YES
1087 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE
1088 | YES_ERROR
1089 | CLANG_WARN_EMPTY_BODY
1090 | YES
1091 | CLANG_WARN_ENUM_CONVERSION
1092 | YES
1093 | CLANG_WARN_INFINITE_RECURSION
1094 | YES
1095 | CLANG_WARN_INT_CONVERSION
1096 | YES
1097 | CLANG_WARN_OBJC_ROOT_CLASS
1098 | YES_ERROR
1099 | CLANG_WARN_SUSPICIOUS_MOVE
1100 | YES
1101 | CLANG_WARN_UNREACHABLE_CODE
1102 | YES
1103 | CLANG_WARN__DUPLICATE_METHOD_MATCH
1104 | YES
1105 | CODE_SIGN_IDENTITY[sdk=iphoneos*]
1106 | iPhone Developer
1107 | COPY_PHASE_STRIP
1108 | NO
1109 | DEBUG_INFORMATION_FORMAT
1110 | dwarf-with-dsym
1111 | ENABLE_NS_ASSERTIONS
1112 | NO
1113 | ENABLE_STRICT_OBJC_MSGSEND
1114 | YES
1115 | GCC_C_LANGUAGE_STANDARD
1116 | gnu99
1117 | GCC_NO_COMMON_BLOCKS
1118 | YES
1119 | GCC_WARN_64_TO_32_BIT_CONVERSION
1120 | YES
1121 | GCC_WARN_ABOUT_RETURN_TYPE
1122 | YES_ERROR
1123 | GCC_WARN_UNDECLARED_SELECTOR
1124 | YES
1125 | GCC_WARN_UNINITIALIZED_AUTOS
1126 | YES_AGGRESSIVE
1127 | GCC_WARN_UNUSED_FUNCTION
1128 | YES
1129 | GCC_WARN_UNUSED_VARIABLE
1130 | YES
1131 | IPHONEOS_DEPLOYMENT_TARGET
1132 | 9.3
1133 | MTL_ENABLE_DEBUG_INFO
1134 | NO
1135 | SDKROOT
1136 | iphoneos
1137 | SWIFT_OPTIMIZATION_LEVEL
1138 | -Owholemodule
1139 | VALIDATE_PRODUCT
1140 | YES
1141 |
1142 | isa
1143 | XCBuildConfiguration
1144 | name
1145 | Release
1146 |
1147 | F3594B521D99FCC70046DA07
1148 |
1149 | buildConfigurations
1150 |
1151 | F3594B531D99FCC70046DA07
1152 | F3594B541D99FCC70046DA07
1153 |
1154 | defaultConfigurationIsVisible
1155 | 0
1156 | defaultConfigurationName
1157 | Release
1158 | isa
1159 | XCConfigurationList
1160 |
1161 | F3594B531D99FCC70046DA07
1162 |
1163 | baseConfigurationReference
1164 | 08EF98704AF410F61BBA9BD1
1165 | buildSettings
1166 |
1167 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES
1168 | YES
1169 | ASSETCATALOG_COMPILER_APPICON_NAME
1170 | AppIcon
1171 | INFOPLIST_FILE
1172 | SimpleNoteTakingApp/Info.plist
1173 | LD_RUNPATH_SEARCH_PATHS
1174 | $(inherited) @executable_path/Frameworks
1175 | PRODUCT_BUNDLE_IDENTIFIER
1176 | appcoda.SimpleNoteTakingApp
1177 | PRODUCT_NAME
1178 | $(TARGET_NAME)
1179 | SWIFT_VERSION
1180 | 3.0
1181 |
1182 | isa
1183 | XCBuildConfiguration
1184 | name
1185 | Debug
1186 |
1187 | F3594B541D99FCC70046DA07
1188 |
1189 | baseConfigurationReference
1190 | B20011C818B47727914AC427
1191 | buildSettings
1192 |
1193 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES
1194 | YES
1195 | ASSETCATALOG_COMPILER_APPICON_NAME
1196 | AppIcon
1197 | INFOPLIST_FILE
1198 | SimpleNoteTakingApp/Info.plist
1199 | LD_RUNPATH_SEARCH_PATHS
1200 | $(inherited) @executable_path/Frameworks
1201 | PRODUCT_BUNDLE_IDENTIFIER
1202 | appcoda.SimpleNoteTakingApp
1203 | PRODUCT_NAME
1204 | $(TARGET_NAME)
1205 | SWIFT_VERSION
1206 | 3.0
1207 |
1208 | isa
1209 | XCBuildConfiguration
1210 | name
1211 | Release
1212 |
1213 | F3594B551D99FCC70046DA07
1214 |
1215 | buildConfigurations
1216 |
1217 | F3594B561D99FCC70046DA07
1218 | F3594B571D99FCC70046DA07
1219 |
1220 | defaultConfigurationIsVisible
1221 | 0
1222 | defaultConfigurationName
1223 | Release
1224 | isa
1225 | XCConfigurationList
1226 |
1227 | F3594B561D99FCC70046DA07
1228 |
1229 | baseConfigurationReference
1230 | 2BD90F8AC0B31C6DB7A3DFD7
1231 | buildSettings
1232 |
1233 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES
1234 | YES
1235 | BUNDLE_LOADER
1236 | $(TEST_HOST)
1237 | INFOPLIST_FILE
1238 | SimpleNoteTakingAppTests/Info.plist
1239 | LD_RUNPATH_SEARCH_PATHS
1240 | $(inherited) @executable_path/Frameworks @loader_path/Frameworks
1241 | PRODUCT_BUNDLE_IDENTIFIER
1242 | appcoda.SimpleNoteTakingAppTests
1243 | PRODUCT_NAME
1244 | $(TARGET_NAME)
1245 | SWIFT_VERSION
1246 | 3.0
1247 | TEST_HOST
1248 | $(BUILT_PRODUCTS_DIR)/SimpleNoteTakingApp.app/SimpleNoteTakingApp
1249 |
1250 | isa
1251 | XCBuildConfiguration
1252 | name
1253 | Debug
1254 |
1255 | F3594B571D99FCC70046DA07
1256 |
1257 | baseConfigurationReference
1258 | 5C5AADD9672AD06049495439
1259 | buildSettings
1260 |
1261 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES
1262 | YES
1263 | BUNDLE_LOADER
1264 | $(TEST_HOST)
1265 | INFOPLIST_FILE
1266 | SimpleNoteTakingAppTests/Info.plist
1267 | LD_RUNPATH_SEARCH_PATHS
1268 | $(inherited) @executable_path/Frameworks @loader_path/Frameworks
1269 | PRODUCT_BUNDLE_IDENTIFIER
1270 | appcoda.SimpleNoteTakingAppTests
1271 | PRODUCT_NAME
1272 | $(TARGET_NAME)
1273 | SWIFT_VERSION
1274 | 3.0
1275 | TEST_HOST
1276 | $(BUILT_PRODUCTS_DIR)/SimpleNoteTakingApp.app/SimpleNoteTakingApp
1277 |
1278 | isa
1279 | XCBuildConfiguration
1280 | name
1281 | Release
1282 |
1283 | F3594B661D9B552D0046DA07
1284 |
1285 | children
1286 |
1287 | F3594B671D9B552D0046DA07
1288 |
1289 | isa
1290 | PBXGroup
1291 | path
1292 | Config
1293 | sourceTree
1294 | <group>
1295 |
1296 | F3594B671D9B552D0046DA07
1297 |
1298 | fileEncoding
1299 | 4
1300 | isa
1301 | PBXFileReference
1302 | lastKnownFileType
1303 | sourcecode.swift
1304 | path
1305 | Constants.swift
1306 | sourceTree
1307 | <group>
1308 |
1309 | F3594B681D9B552D0046DA07
1310 |
1311 | children
1312 |
1313 | 18EEB4451DB63F02008D21CC
1314 | F3594B691D9B552D0046DA07
1315 | F3594B6A1D9B552D0046DA07
1316 | F3594B6B1D9B552D0046DA07
1317 |
1318 | isa
1319 | PBXGroup
1320 | path
1321 | Extensions
1322 | sourceTree
1323 | <group>
1324 |
1325 | F3594B691D9B552D0046DA07
1326 |
1327 | fileEncoding
1328 | 4
1329 | isa
1330 | PBXFileReference
1331 | lastKnownFileType
1332 | sourcecode.swift
1333 | path
1334 | UIStoryboard+Extensions.swift
1335 | sourceTree
1336 | <group>
1337 |
1338 | F3594B6A1D9B552D0046DA07
1339 |
1340 | fileEncoding
1341 | 4
1342 | isa
1343 | PBXFileReference
1344 | lastKnownFileType
1345 | sourcecode.swift
1346 | path
1347 | UITableView+Extensions.swift
1348 | sourceTree
1349 | <group>
1350 |
1351 | F3594B6B1D9B552D0046DA07
1352 |
1353 | fileEncoding
1354 | 4
1355 | isa
1356 | PBXFileReference
1357 | lastKnownFileType
1358 | sourcecode.swift
1359 | path
1360 | UIViewController+Extensions.swift
1361 | sourceTree
1362 | <group>
1363 |
1364 | F3594B6C1D9B552D0046DA07
1365 |
1366 | children
1367 |
1368 | F3594B6D1D9B552D0046DA07
1369 |
1370 | isa
1371 | PBXGroup
1372 | path
1373 | Models
1374 | sourceTree
1375 | <group>
1376 |
1377 | F3594B6D1D9B552D0046DA07
1378 |
1379 | fileEncoding
1380 | 4
1381 | isa
1382 | PBXFileReference
1383 | lastKnownFileType
1384 | sourcecode.swift
1385 | path
1386 | Note.swift
1387 | sourceTree
1388 | <group>
1389 |
1390 | F3594B6E1D9B552D0046DA07
1391 |
1392 | children
1393 |
1394 | F3594B6F1D9B552D0046DA07
1395 | F3594B701D9B552D0046DA07
1396 | F3594B711D9B552D0046DA07
1397 |
1398 | isa
1399 | PBXGroup
1400 | path
1401 | ViewControllers
1402 | sourceTree
1403 | <group>
1404 |
1405 | F3594B6F1D9B552D0046DA07
1406 |
1407 | fileEncoding
1408 | 4
1409 | isa
1410 | PBXFileReference
1411 | lastKnownFileType
1412 | sourcecode.swift
1413 | path
1414 | HomeViewController.swift
1415 | sourceTree
1416 | <group>
1417 |
1418 | F3594B701D9B552D0046DA07
1419 |
1420 | fileEncoding
1421 | 4
1422 | isa
1423 | PBXFileReference
1424 | lastKnownFileType
1425 | sourcecode.swift
1426 | path
1427 | LoginViewController.swift
1428 | sourceTree
1429 | <group>
1430 |
1431 | F3594B711D9B552D0046DA07
1432 |
1433 | fileEncoding
1434 | 4
1435 | isa
1436 | PBXFileReference
1437 | lastKnownFileType
1438 | sourcecode.swift
1439 | path
1440 | NoteViewController.swift
1441 | sourceTree
1442 | <group>
1443 |
1444 | F3594B721D9B552D0046DA07
1445 |
1446 | fileRef
1447 | F3594B671D9B552D0046DA07
1448 | isa
1449 | PBXBuildFile
1450 |
1451 | F3594B731D9B552D0046DA07
1452 |
1453 | fileRef
1454 | F3594B691D9B552D0046DA07
1455 | isa
1456 | PBXBuildFile
1457 |
1458 | F3594B741D9B552D0046DA07
1459 |
1460 | fileRef
1461 | F3594B6A1D9B552D0046DA07
1462 | isa
1463 | PBXBuildFile
1464 |
1465 | F3594B751D9B552D0046DA07
1466 |
1467 | fileRef
1468 | F3594B6B1D9B552D0046DA07
1469 | isa
1470 | PBXBuildFile
1471 |
1472 | F3594B761D9B552D0046DA07
1473 |
1474 | fileRef
1475 | F3594B6D1D9B552D0046DA07
1476 | isa
1477 | PBXBuildFile
1478 |
1479 | F3594B771D9B552D0046DA07
1480 |
1481 | fileRef
1482 | F3594B6F1D9B552D0046DA07
1483 | isa
1484 | PBXBuildFile
1485 |
1486 | F3594B781D9B552D0046DA07
1487 |
1488 | fileRef
1489 | F3594B701D9B552D0046DA07
1490 | isa
1491 | PBXBuildFile
1492 |
1493 | F3594B791D9B552D0046DA07
1494 |
1495 | fileRef
1496 | F3594B711D9B552D0046DA07
1497 | isa
1498 | PBXBuildFile
1499 |
1500 | F3594B7A1D9B55400046DA07
1501 |
1502 | children
1503 |
1504 | F3594B3F1D99FCC70046DA07
1505 | F3594B411D99FCC70046DA07
1506 | F3594B441D99FCC70046DA07
1507 |
1508 | isa
1509 | PBXGroup
1510 | name
1511 | Support
1512 | sourceTree
1513 | <group>
1514 |
1515 |
1516 | rootObject
1517 | F3594B2D1D99FCC70046DA07
1518 |
1519 |
1520 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/27/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 | var window: UIWindow?
14 |
15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
16 | return true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
38 |
44 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
154 |
155 |
156 |
157 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Config/Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Constants.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/27/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | let correctUsername = "appcoda"
10 | let correctPassword = "password"
11 |
12 | let notificationNewNoteCreated = "NewNoteCreated"
13 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Extensions/UIColor+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIColor+Extensions.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 | class func colorWithRed(red: NSInteger, green: NSInteger, blue: NSInteger) -> UIColor {
13 | let max: CGFloat = 255.0
14 | return UIColor(red: CGFloat(red) / max, green: CGFloat(green) / max, blue: CGFloat(blue) / max, alpha: 1)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Extensions/UIStoryboard+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIStoryboard+Extensions.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/27/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIStoryboard {
12 | class func main() -> UIStoryboard {
13 | return UIStoryboard(name: "Main", bundle: nil)
14 | }
15 |
16 | class func initializeViewController(_ viewController: T.Type) -> T where T: UIViewController {
17 | return UIStoryboard.main().instantiateViewController(withIdentifier: String(describing: viewController)) as! T
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Extensions/UITableView+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UITableView+Extensions.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/27/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UITableView {
12 | func defaultCellWithReuseID(_ reuseID: String) -> UITableViewCell {
13 | return self.dequeueReusableCell(withIdentifier: reuseID) ?? UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: reuseID)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Extensions/UIViewController+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UIViewController+Extensions.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/27/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIViewController {
12 | func showErrorAlertWithMessage(_ message: String) {
13 | let alertController = UIAlertController(title: "Error", message:message, preferredStyle: .alert)
14 | alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil))
15 | present(alertController, animated: true, completion: nil)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/Models/Note.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Note.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/27/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import RealmSwift
10 |
11 | class Note: Object {
12 | dynamic var title: String = ""
13 | dynamic var body: String = ""
14 | }
15 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/ViewControllers/HomeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HomeViewController.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/27/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import RealmSwift
11 |
12 | class HomeViewController: UIViewController {
13 | @IBOutlet weak var emptyNotesLabel: UILabel!
14 | @IBOutlet weak var notesTableView: UITableView!
15 |
16 | var notes: Results?
17 |
18 | lazy var noteViewController : NoteViewController = {
19 | let viewController = UIStoryboard.initializeViewController(NoteViewController.self)
20 | let _ = viewController.view
21 | return viewController
22 | }()
23 |
24 | override func viewDidLoad() {
25 | super.viewDidLoad()
26 | NotificationCenter.default.addObserver(self, selector: #selector(HomeViewController.onNewNoteCreated), name: NSNotification.Name(rawValue: notificationNewNoteCreated), object: nil)
27 | }
28 |
29 | override func viewWillAppear(_ animated: Bool) {
30 | super.viewWillAppear(animated)
31 | updateNotes()
32 | }
33 |
34 | @IBAction func onTapAddNoteButton(_ sender: AnyObject) {
35 | noteViewController.note = nil
36 | navigationController?.pushViewController(noteViewController, animated: true)
37 | }
38 |
39 | func onNewNoteCreated() {
40 | updateTableViewVisibility()
41 | notesTableView.reloadData()
42 | }
43 | }
44 |
45 | extension HomeViewController {
46 | func updateNotes() {
47 | let realm = try! Realm()
48 | notes = realm.objects(Note.self)
49 | updateTableViewVisibility()
50 | notesTableView.reloadData()
51 | }
52 |
53 | func updateTableViewVisibility() {
54 | emptyNotesLabel.isHidden = (notes?.count)! > 0
55 | notesTableView.isHidden = !emptyNotesLabel.isHidden
56 | }
57 | }
58 |
59 | extension HomeViewController: UITableViewDataSource, UITableViewDelegate {
60 | func numberOfSections(in tableView: UITableView) -> Int {
61 | return 1
62 | }
63 |
64 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
65 | return notes?.count ?? 0
66 | }
67 |
68 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
69 | let cell = tableView.defaultCellWithReuseID("reuseID")
70 | let note = notes![indexPath.row]
71 | cell.textLabel?.text = note.title
72 | cell.detailTextLabel?.text = note.body
73 | return cell
74 | }
75 |
76 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
77 | tableView.deselectRow(at: indexPath, animated: true)
78 | noteViewController.note = notes![indexPath.row]
79 | navigationController?.pushViewController(noteViewController, animated: true)
80 | }
81 |
82 | func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
83 | return true
84 | }
85 |
86 | func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
87 | if editingStyle == .delete {
88 | let realm = try! Realm()
89 | try! realm.write {
90 | realm.delete(notes![indexPath.row])
91 | }
92 | tableView.beginUpdates()
93 | tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.automatic)
94 | tableView.endUpdates()
95 | updateTableViewVisibility()
96 | }
97 | }
98 |
99 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
100 | return 60
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/ViewControllers/LoginViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/27/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class LoginViewController: UIViewController {
12 | @IBOutlet weak var usernameTextField: UITextField!
13 | @IBOutlet weak var passwordTextField: UITextField!
14 |
15 | lazy var homeViewController : HomeViewController = {
16 | let viewController = UIStoryboard.initializeViewController(HomeViewController.self)
17 | return viewController
18 | }()
19 |
20 | override func viewWillAppear(_ animated: Bool) {
21 | super.viewWillAppear(animated)
22 | navigationController?.setNavigationBarHidden(true, animated: false)
23 | }
24 |
25 | override func viewWillDisappear(_ animated: Bool) {
26 | super.viewWillDisappear(animated)
27 | navigationController?.setNavigationBarHidden(false, animated: false)
28 | }
29 |
30 | @IBAction func onTapLoginButton(_ sender: AnyObject) {
31 | guard let username = usernameTextField.text , username.characters.count > 0 else {
32 | showErrorAlertWithMessage("Username cannot be empty")
33 | return
34 | }
35 | guard let password = passwordTextField.text , password.characters.count > 0 else {
36 | showErrorAlertWithMessage("Password cannot be empty")
37 | return
38 | }
39 | guard username == correctUsername && password == correctPassword else {
40 | showErrorAlertWithMessage("Username or password is incorrect")
41 | return
42 | }
43 | navigationController?.pushViewController(homeViewController, animated: true)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/SimpleNoteTakingApp/ViewControllers/NoteViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoteViewController.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import RealmSwift
11 | fileprivate func < (lhs: T?, rhs: T?) -> Bool {
12 | switch (lhs, rhs) {
13 | case let (l?, r?):
14 | return l < r
15 | case (nil, _?):
16 | return true
17 | default:
18 | return false
19 | }
20 | }
21 |
22 | fileprivate func > (lhs: T?, rhs: T?) -> Bool {
23 | switch (lhs, rhs) {
24 | case let (l?, r?):
25 | return l > r
26 | default:
27 | return rhs < lhs
28 | }
29 | }
30 |
31 |
32 | class NoteViewController: UIViewController {
33 | var note: Note? {
34 | didSet {
35 | guard titleTextField != nil && bodyTextView != nil else { return }
36 | titleTextField.text = note?.title
37 | bodyTextView.text = note?.body
38 | navigationItem.rightBarButtonItem?.title = note != nil ? "Update" : "Create"
39 | onNoteTitleTextFieldChanged(titleTextField)
40 | }
41 | }
42 |
43 | @IBOutlet weak var titleTextField: UITextField!
44 | @IBOutlet weak var bodyTextView: UITextView!
45 |
46 | override func viewDidLoad() {
47 | super.viewDidLoad()
48 | setupNavigationButtons()
49 | setupBodyTextView()
50 | }
51 |
52 | func onTapCreateButton(_ sender: AnyObject) {
53 | _ = navigationController?.popViewController(animated: true)
54 | saveNoteToDatabase()
55 | NotificationCenter.default.post(name: Notification.Name(rawValue: notificationNewNoteCreated), object: nil)
56 | }
57 |
58 | func onTapCancelButton(_ sender: AnyObject) {
59 | _ = navigationController?.popViewController(animated: true)
60 | }
61 |
62 | @IBAction func onNoteTitleTextFieldChanged(_ sender: AnyObject) {
63 | navigationItem.rightBarButtonItem?.isEnabled = titleTextField.text?.characters.count > 0
64 | }
65 | }
66 |
67 | extension NoteViewController {
68 | fileprivate func setupNavigationButtons() {
69 | navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Create", style: .plain, target: self, action: #selector(NoteViewController.onTapCreateButton))
70 | navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(NoteViewController.onTapCancelButton))
71 | }
72 |
73 | fileprivate func setupBodyTextView() {
74 | bodyTextView.layer.borderWidth = 0.5
75 | bodyTextView.layer.borderColor = UIColor.colorWithRed(red: 204, green: 204, blue: 204).cgColor
76 | bodyTextView.layer.cornerRadius = 4;
77 | }
78 |
79 | fileprivate func saveNoteToDatabase() {
80 | let realm = try! Realm()
81 | try! realm.write {
82 | let note = self.note ?? Note()
83 | note.title = titleTextField.text!
84 | note.body = bodyTextView.text!
85 | realm.add(note)
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/Extensions/KIF+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KIF+Extensions.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import KIF
10 |
11 | extension XCTestCase {
12 | func tester(_ file : String = #file, _ line : Int = #line) -> KIFUITestActor {
13 | return KIFUITestActor(inFile: file, atLine: line, delegate: self)
14 | }
15 |
16 | func system(_ file : String = #file, _ line : Int = #line) -> KIFSystemTestActor {
17 | return KIFSystemTestActor(inFile: file, atLine: line, delegate: self)
18 | }
19 | }
20 |
21 | extension KIFTestActor {
22 | func tester(_ file : String = #file, _ line : Int = #line) -> KIFUITestActor {
23 | return KIFUITestActor(inFile: file, atLine: line, delegate: self)
24 | }
25 |
26 | func system(_ file : String = #file, _ line : Int = #line) -> KIFSystemTestActor {
27 | return KIFSystemTestActor(inFile: file, atLine: line, delegate: self)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/Features/BaseUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BaseUITests.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | import KIF
10 | import Realm
11 | import RealmSwift
12 |
13 | class BaseUITests: KIFTestCase {
14 | override func beforeAll() {
15 | super.beforeAll()
16 | useTestDatabase()
17 | }
18 |
19 | override func beforeEach() {
20 | super.beforeEach()
21 | backToRoot()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/Features/HomeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoteTests.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | class HomeTests: BaseUITests {
10 |
11 | override func beforeEach() {
12 | super.beforeEach()
13 | haveNoNotes()
14 | }
15 |
16 | func testNoNotes() {
17 | visitHomeScreen()
18 | expectToSeeLabel("No notes")
19 | expectNotToSeeNoteList()
20 | }
21 |
22 | func testCreateNewNote() {
23 | visitHomeScreen()
24 | tapButton("Add note")
25 | expectTheCreateButtonToBeDisabled()
26 | fillInNoteTitle("new note")
27 | expectTheCreateButtonToBeEnabled()
28 | fillInNoteBody("new body")
29 | tapButton("Create")
30 | expectToSeeNoteWithTitle("new note", body: "new body", atRow: 0)
31 | expectNumberOfNotesInListToEqual(1)
32 | }
33 |
34 | func testEditNote() {
35 | have3Notes()
36 | visitHomeScreen()
37 | tapOnNoteAtRow(1)
38 | updateNoteTitleTo("updated note")
39 | updateNoteBodyTo("updated body")
40 | tapButton("Update")
41 | expectToSeeNoteWithTitle("updated note", body: "updated body", atRow: 1)
42 | }
43 |
44 | func testDeleteNote() {
45 | have3Notes()
46 | visitHomeScreen()
47 | deleteANote()
48 | expectNumberOfNotesInListToEqual(2)
49 | deleteANote()
50 | expectNumberOfNotesInListToEqual(1)
51 | deleteANote()
52 | expectToSeeLabel("No notes")
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/Features/LoginTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginTests.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | class LoginTests: BaseUITests {
10 | override func beforeEach() {
11 | super.beforeEach()
12 | clearOutUsernameAndPasswordFields()
13 | }
14 |
15 | func testEmptyUsername() {
16 | tapButton("Login")
17 | expectToSeeAlert("Username cannot be empty")
18 | tapButton("OK")
19 | }
20 |
21 | func testEmptyPassword() {
22 | fillInUsername()
23 | tapButton("Login")
24 | expectToSeeAlert("Password cannot be empty")
25 | tapButton("OK")
26 | }
27 |
28 | func testWrongUsernameOrPassword() {
29 | fillInUsername()
30 | fillInWrongPassword()
31 | tapButton("Login")
32 | expectToSeeAlert("Username or password is incorrect")
33 | tapButton("OK")
34 | }
35 |
36 | func testCorrectUsernameAndPassword() {
37 | fillInUsername()
38 | fillInCorrectPassword()
39 | tapButton("Login")
40 | expectToGoToHomeScreen()
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/SimpleNoteTakingAppTests-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/Steps/CommonSteps.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommonSteps.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | @testable import SimpleNoteTakingApp
10 | import RealmSwift
11 |
12 | extension BaseUITests {
13 | func tapButton(_ buttonName: String) {
14 | tester().tapView(withAccessibilityLabel: buttonName)
15 | }
16 |
17 | func expectToSeeAlert(_ message: String) {
18 | expectToSee(message)
19 | }
20 |
21 | func fillIn(_ accessibilityLabel: String, withText text: String) {
22 | tester().clearText(fromAndThenEnterText: text, intoViewWithAccessibilityLabel: accessibilityLabel)
23 | }
24 |
25 | func backToRoot() {
26 | if let navigationController = UIApplication.shared.keyWindow?.rootViewController as? UINavigationController {
27 | navigationController.popToRootViewController(animated: false)
28 | }
29 | }
30 |
31 | func fillInUsername() {
32 | fillIn("Login - Username", withText: correctUsername)
33 | }
34 |
35 | func visitHomeScreen() {
36 | fillInUsername()
37 | fillInCorrectPassword()
38 | tapButton("Login")
39 | }
40 |
41 | func fillInCorrectPassword() {
42 | fillIn("Login - Password", withText: correctPassword)
43 | }
44 |
45 |
46 | func useTestDatabase() {
47 | Realm.Configuration.defaultConfiguration.inMemoryIdentifier = name
48 | }
49 |
50 | func clearDatabase() {
51 | let realm = try! Realm()
52 | try! realm.write {
53 | realm.deleteAll()
54 | }
55 | }
56 |
57 | func expectToSee(_ text: String) {
58 | tester().waitForView(withAccessibilityLabel: text)
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/Steps/HomeSteps.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NoteSteps.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | @testable import SimpleNoteTakingApp
10 | import RealmSwift
11 | import Nimble
12 |
13 | extension HomeTests {
14 |
15 | func haveNoNotes() {
16 | clearDatabase()
17 | }
18 |
19 | func expectTheCreateButtonToBeDisabled() {
20 | let createButton = tester().waitForView(withAccessibilityLabel: "Create") as! UIButton
21 | expect(createButton.isEnabled) == false
22 | }
23 |
24 | func expectTheCreateButtonToBeEnabled() {
25 | let createButton = tester().waitForView(withAccessibilityLabel: "Create") as! UIButton
26 | expect(createButton.isEnabled) == true
27 | }
28 |
29 | func expectNotToSeeNoteList() {
30 | tester().waitForAbsenceOfView(withAccessibilityLabel: "Note - Table View")
31 | }
32 |
33 | func expectToSeeNoteWithTitle(_ title: String, body: String, atRow row: NSInteger) {
34 | let noteCell = tester().waitForCell(at: IndexPath(row: row, section: 0), inTableViewWithAccessibilityIdentifier: "Note - TableView")
35 | expect(noteCell?.textLabel?.text) == title
36 | expect(noteCell?.detailTextLabel?.text) == body
37 | }
38 |
39 | func have3Notes() {
40 | let realm = try! Realm()
41 | try! realm.write {
42 | for i in 0...2 {
43 | let note = Note()
44 | note.title = "title \(i)"
45 | note.body = "body \(i)"
46 | realm.add(note)
47 | }
48 | }
49 | }
50 |
51 | func fillInNoteTitle(_ title: String) {
52 | fillIn("Note - Title", withText: title)
53 | }
54 |
55 | func fillInNoteBody(_ body: String) {
56 | fillIn("Note - Body", withText: body)
57 | }
58 |
59 |
60 | func updateNoteTitleTo(_ title: String) {
61 | fillInNoteTitle(title)
62 | }
63 |
64 | func updateNoteBodyTo(_ body: String) {
65 | fillInNoteBody(body)
66 | }
67 |
68 | func tapOnNoteAtRow(_ row: Int) {
69 | let indexPath = IndexPath(row: row, section: 0)
70 | tester().tapRow(at: indexPath, inTableViewWithAccessibilityIdentifier: "Note - TableView")
71 | }
72 |
73 | func expectNumberOfNotesInListToEqual(_ count: Int) {
74 | let noteTableView = tester().waitForView(withAccessibilityLabel: "Note - TableView") as! UITableView
75 | expect(noteTableView.numberOfRows(inSection: 0)) == count
76 | }
77 |
78 | func deleteANote() {
79 | let noteTableView = tester().waitForView(withAccessibilityLabel: "Note - TableView") as! UITableView
80 | tester().swipeRow(at: IndexPath(row: 0, section: 0), in: noteTableView, in: .left)
81 | tapButton("Delete")
82 | }
83 |
84 | func expectToSeeLabel(_ label: String) {
85 | expectToSee(label)
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/SimpleNoteTakingAppTests/Steps/LoginSteps.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoginSteps.swift
3 | // SimpleNoteTakingApp
4 | //
5 | // Created by Hoang Tran on 9/28/16.
6 | // Copyright © 2016 AppCoda. All rights reserved.
7 | //
8 |
9 | extension LoginTests {
10 | func clearOutUsernameAndPasswordFields() {
11 | tester().clearTextFromView(withAccessibilityLabel: "Login - Username")
12 | tester().clearTextFromView(withAccessibilityLabel: "Login - Password")
13 | }
14 |
15 | func fillInWrongPassword() {
16 | fillIn("Login - Password", withText: "wrongPassword")
17 | }
18 |
19 | func expectToGoToHomeScreen() {
20 | tester().waitForAbsenceOfView(withAccessibilityLabel: "Login - Username")
21 | tester().waitForAbsenceOfView(withAccessibilityLabel: "Login - Password")
22 | tester().waitForAbsenceOfView(withAccessibilityLabel: "Login")
23 | tester().waitForView(withAccessibilityLabel: "No notes")
24 | tester().waitForView(withAccessibilityLabel: "Add note")
25 | }
26 | }
27 |
--------------------------------------------------------------------------------